1 关联查询映射
1.1 分析数据模型
思路 :
每张表记录的数据内容
每张表重要的字段(主键,外键,非空字段)
表与表之间的关系(外键关系)
表与表之间的业务关系(建立在某个业务意义基础上去分析)
如图:
1.2 一对一查询
有三种实现方法:
resultType
resultMap中的association嵌套查询
resultMap中的嵌套结果
需求:
进行订单查询,包括用户的姓名和地址信息
SQL语句:
SELECT
orders.id,orders.user_id,orders.number,orders.createtime,orders.note,user.username,user.address
FROM
orders, user
WHERE
orders.user_id = user.id;
方法一:resultType
复杂查询时,单表对应的domain类已不能满足输出结果集的映射。
所以要根据需求建立一个扩展类来作为resultType的类型。
创建domain类(OrdersExt.java):
package cn.mybatis.mapper.domain; /** * 使用此类来映射订单和用户的查询结果,此类继承订单,所以是扩展的 * @author 刘泽栋 * @date 2015年6月21日 下午10:08:57 */ public class OrdersExt extends Orders { /** * 添加用户的属性 */ private String username; private String sex; private String address; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } |
编写mapper接口(OrdersMapper.java)
public interface OrdersMapper { // 进行订单查询,包括用户的姓名和地址信息 public List<OrdersExt> findOrders(); } |
编写映射文件(OrdersMapper.xml)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.mybatis.mapper.mapper.OrdersMapper"> <!-- 定义查询订单的SQL片段 --> <sql id="select_orders"> orders.id, orders.user_id, orders.number, orders.createtime, orders.note </sql> <!-- 定义查询用户的SQL片段 --> <sql id="select_user"> user.username, user.address </sql> <!-- 查询订单信息,包括用户的姓名和地址 --> <select id="findOrders" resultType="ordersExt"> SELECT <include refid="select_orders"/>, <include refid="select_user"/> FROM orders, user WHERE orders.user_id = user.id </select> </mapper> |
加载配置文件(sqlMapConfig.xml)
<!-- 批量加载mapper文件,需要mapper接口文件和mapper映射文件名称相同且在同一个包下 --> <mappers> <package name="cn.mybatis.mapper.mapper"/> </mappers> |
编写测试代码(OrdersMapperTest.java)
package cn.mybatis.mapper.mapper; import java.io.InputStream; import java.util.List; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.Test; import cn.mybatis.mapper.domain.OrdersExt; /** * 测试mybatis的关联映射 * @author 刘泽栋 * @date 2015年6月21日 下午10:57:23 */ public class OrdersMapperTest { private SqlSessionFactory sqlSessionFactory; @Before public void setUp() throws Exception { String resource = "sqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } /** * 测试,进行订单查询,包括用户的姓名和地址信息 */ @Test public void testFindOrders() { SqlSession sqlSession = sqlSessionFactory.openSession(); OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class); // 测试 List<OrdersExt> list = ordersMapper.findOrders(); System.out.println(list); sqlSession.close(); } } |
方法二:resultMap的association嵌套查询
修改SQL:
SELECT orders.id,orders.user_id,orders.number,orders.createtime,orders.note FROM orders;
修改domain类(OrdersExt.java):
package cn.mybatis.mapper.domain; /** * 使用此类来映射订单和用户的查询结果,此类继承订单,所以是扩展的 * @author 刘泽栋 * @date 2015年6月21日 下午10:08:57 */ public class OrdersExt extends Orders { /** * 添加用户的属性 */ private String username; private String sex; private String address; // 用户信息 private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "OrdersExt [username=" + username + ", sex=" + sex + ", address=" + address + "]"; } } |
编写mapper接口(OrdersMapper.java):
// 进行订单查询,包括用户的姓名和地址信息(resultMap的嵌套查询) public List<OrdersExt> findOrdersResultMapOfSelect(); |
编写映射文件(OrdersMapper.xml)
<!-- 定义orderUserSelectResultMap 嵌套查询 --> <resultMap type="ordersExt" id="ordersUserSelectResultMap"> <id column="id" property="id"/> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> <!-- 映射一对一关联关系的用户对象(嵌套查询) --> <!-- property:指定关联对象要映射到哪个属性上 javaType:指定关联对象所映射属性的java类型 column:如果使用嵌套查询,则通过column指定子查询的查询条件所对应的结果列 select:指定嵌套查询的子查询statementId --> <association property="user" javaType="cn.mybatis.mapper.domain.User" column="user_id" select="cn.mybatis.mapper.mapper.UserMapper.findUserById"></association> </resultMap> <!-- 进行订单查询,包括用户的姓名和地址信息(resultMap的嵌套查询) --> <select id="findOrdersResultMapOfSelect" resultMap="ordersUserSelectResultMap"> SELECT <include refid="select_orders"/> FROM orders </select> |
加载配置文件(sqlMapConfig.xml)
<!-- 批量加载mapper文件,需要mapper接口文件和mapper映射文件名称相同且在同一个包下 --> <mappers> <package name="cn.mybatis.mapper.mapper"/> </mappers> |
编写测试代码(OrdersMapperTest.java)
/** * 进行订单查询,包括用户的姓名和地址信息(resultMap的嵌套查询) */ @Test public void testFindOrdersResultMapOfSelect() { SqlSession sqlSession = sqlSessionFactory.openSession(); OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class); // 测试 List<OrdersExt> list = ordersMapper.findOrdersResultMapOfSelect(); System.out.println(list); sqlSession.close(); } |
方法三:resultMap的association嵌套结果
SQL语句:
SELECT
orders.id,orders.user_id,orders.number,orders.createtime,orders.note,user.username,user.address
FROM
orders, user
WHERE
orders.user_id = user.id;
编写mapper接口(OrdersMapper.java):
// 进行订单信息查询,包括用户的名称和地址信息(resultMap之嵌套结果) |
编写映射文件(OrdersMapper.xml)
<!-- 定义orderUserResultMap --> <resultMap type="ordersExt" id="ordersUserResultMap"> <id column="id" property="id"/> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> <!-- 映射一对一关联关系的用户对象,采用嵌套结果(内部映射) --> <!-- property:指定关联对象要映射到哪个属性上 javaType:指定关联对象所映射属性的java类型 --> <!-- id标签:指定关联对象结果集的唯一标识,很重要,不写不会报错,但是会影响性能 --> <association property="user" javaType="cn.mybatis.mapper.domain.User"> <id column="user_id" property="id"/> <result column="username" property="username" /> <result column="address" property="address" /> </association> </resultMap> <!-- 进行订单信息查询,包括用户的名称和地址信息 (ResultMap之嵌套结果) --> <select id="findOrdersResultMap" resultMap="ordersUserResultMap"> SELECT <include refid="select_orders"/>, <include refid="select_user"/> FROM orders, user WHERE orders.user_id = user.id </select> |
加载配置文件(sqlMapConfig.xml)
<!-- 批量加载mapper文件,需要mapper接口文件和mapper映射文件名称相同且在同一个包下 --> <mappers> <package name="cn.mybatis.mapper.mapper"/> </mappers> |
编写测试代码(OrdersMapperTest.java)
/** * 进行订单信息查询,包括用户的名称和地址信息(resultMap之嵌套结果) */ @Test public void testFindOrdersResultMap() { SqlSession sqlSession = sqlSessionFactory.openSession(); OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class); // 测试 List<OrdersExt> list = ordersMapper.findOrdersResultMap(); System.out.println(list); sqlSession.close(); } |