MyBatis多表关联查询
如果使用多表查询,那么表之间一定有这三种关系:
- 一对一,比如一个人有且只有一个身份证号
- 一对多,比如一个人可以有多个银行卡
- 多对多,比如一个学生可以选择多个课程,一个课程也可以被多个学生选择
使用MyBatis实现多表查询,根据表与表之间的关系不同,具体实现就会有些不同
首先分析问题:
- 当我们进行多表查询时,返回的结果集一定是两个表中的数据,那么我们总不能再准备一个(包含两个表中所有字段的)POJO来映射这次返回的结果。
- 这时,我们可以考虑让第一个表的POJO包含第二个表的POJO(其实就是:为第一个表的POJO增加一个属性,类型就为第二个表的POJO);然后通过MyBatis提供的手动映射的方式,将结果集 分别 封装到对应的对象中去
一对一关系查询
使用resultMap标签手动映射时,它里面还有一个association子标签,
association:联合标签
- property属性:值为第一表中添加的POJO属性名
- JavaType属性:值为对应的POJO的类型
案例:查询出订单的信息,并且包含该订单的用户信息
public class OrderVo {
private Integer id;
private Integer uid;
private String number;
private Timestamp createtime;
private String des;
private User user;//订单中的用户信息可以放在这个user属性中
}
<!-- 查询出来的字段有:订单id,该订单的用户id,订单编号,订单创建时间,订单简介,对应用户的id,用户名-->
<select id="findOrderUserList" resultMap="resultMap_order_user">
SELECT o.id,o.uid,o.number,o.createtime,o.des,u.id,u.username
FROM t_orders o JOIN t_user u ON o.uid=u.id
</select>
<resultMap id="resultMap_order_user" type="ordervo">
<id column="id" property="id"/>
<result column="uid" property="uid"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<association property="user" javaType="User">
<id column="id" property="id"/>
<result column="username" property="username"/>
</association>
</resultMap>
使用association标签,将属于用户的字段放入order对象的user属性中
一对多关系查询
一对多的关系,只需要给第一个表中对应的POJO准备一个放多个第二个表中POJO对象的列表即可
这样第一个表中对应第二个表中的多条数据就可以存放在这个list中
这时就不能使用association标签了,resultMap标签中还有另一个collection子标签
collection:
- property属性:值为POJO中的属性名
- ofType属性:值为该集合的泛型类型
案例:查询出所有用户,并且包含每个用户的所有订单信息
public class User {
private Integer id;
private String username;
private String password;
private String email;
private String remark;
private List<OrderVo> orderList;
}
<!-- 查询出来的字段有:用户的id,用户名,密码,邮箱,说明,用户的订单id,订单对应的用户id,订单的简介-->
<select id="findUserOrder" resultMap="result_user_orders">
SELECT u.id as uid,u.username,u.password,u.email,u.remark,o.id,o.uid,o.des
FROM t_user u INNER JOIN t_orders o ON u.id=o.uid
</select>
<resultMap id="result_user_orders" type="User">
<id column="uid" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="email" property="email"/>
<result column="remark" property="remark"/>
<collection property="orderList" ofType="OrderVo">
<id property="id" column="id"/>
<result property="uid" column="uid"/>
<result property="des" column="des"/>
</collection>
</resultMap>
collection标签可以将属于订单的字段放到一个OrderVo对象中,再将该用户的所有Order放到user的orderList属性中
多对多关系查询
要实现多对多的关系,那么一定会有一个第三张表作为关系表
我们要把多对多的关系理解为一个双向的一对多:表一中的一条数据对应关系表中的多条记录,表二中的一条数据也对应关系表中的多条记录
两个POJO中分别包含对方对象List的引用
案例:查询每一个角色分别对应哪些用户
(一个用户可以有多个角色,一个角色中可以有多个用户)
public class Role {
private Integer id;
private String name;
private String keyword;
private List<User> userList;
}
<!-- 查询出来的字段有:角色的id,角色名,角色描述,对应用户的id,用户名,密码,邮箱-->
<select id="findRoleUserList" resultMap="result_role_users">
SELECT r.id as rid,r.name,r.keyword,u.id as uid,u.username,u.password,u.email
FROM t_role r LEFT JOIN t_role_user ru ON r.id=ru.role_id
LEFT JOIN t_user u ON ru.user_id=u.id
</select>
<resultMap id="result_role_users" type="role">
<id column="rid" property="id"/>
<result column="name" property="name"/>
<result column="keyword" property="keyword"/>
<collection property="userList" ofType="User">
<id column="id" property="uid"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="email" property="email"/>
</collection>
</resultMap>
既然是对多的关系,那么同样,也可以:
查询每一个用户都有哪些角色信息
public class User {
private Integer id;
private String username;
private String password;
private String email;
private String remark;
private List<Role> roleList;
}
<!-- 查询出来的字段有:用户的id,用户名,密码,邮箱,说明,对应角色的id,角色名,角色简介-->
<select id="findUserRoleList" resultMap="result_user_roles">
SELECT u.id as uid,u.username,u.password,u.email,u.remark,r.id as rid,r.name,r.keyword
WHERE t_user u LEFT JOIN t_role_user ru ON u.id=ru.user_id
LEFT JOIN t_role r ON ru.role_id=r.id
</select>
<resultMap id="result_user_roles" type="user">
<id column="uid" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="email" property="email"/>
<result column="remark" property="remark"/>
<collection property="roleList" ofType="role">
<id column="rid" property="id"/>
<result column="name" property="name"/>
<result column="keyword" property="keyword"/>
</collection>
</resultMap>
总结:
- association:一对一关联时使用,封装为一个对象属性
- collection:一对多关联时使用,封装为一个对象集合