collection 集合的嵌套结果映射
collection 标签中的属性与 association 标签一致,集合的嵌套结果映射就是指通过一次SQL查询将所有的结果查询出来,然后通过配置的结果映射,将数据映射到不同的对象中去。
示例如下:
/**
* 用户表
*/
public class SysUser {
//其他属性
/**
* 用户的角色集合
*/
private List<SysRole> roleList;
//其他getter和setter方法
public List<SysRole> getRoleList() {
return roleList;
}
public void setRoleList(List<SysRole> roleList) {
this.roleList = roleList;
}
这里 userRoleListMap 继承了 userMap 中的字段,collection 使用了RoleMapper中现有的 roleMap。
<resultMap id="userRoleListMap" type="tk.mybatis.simple.model.SysUser" extends="userMap">
<collection property="roleList" columnPrefix="role_"
resultMap="tk.mybatis.simple.mapper.RoleMapper.roleMap"/>
</resultMap>
<select id="selectAllUserAndRoles" resultMap="userRoleListMap">
select
u.id,
u.user_name,
u.user_password,
u.user_info,
u.create_time,
r.id role_id,
r.role_name role_role_name,
r.enabled role_enabled,
r.create_by role_create_by,
r.create_time role_create_time,
from sys_user u
inner join sys_user_role ur on u.id = ur.user_id
inner join sys_role r on r.id = ur.role_id
</select>
MyBatis 在处理结果时,会判断结果是否相同,以此来进行数据的合并,如果是相同的结果,则只保留第一个结果。MyBatis 判断结果相同时,最简单的情况是在映射配置中有 id 标签,在 userRoleListMap 继承的 userMap 中配置有:
<id property="id" column="id"/>
id 标签配置的字段一般为表的主键(联合主键可以配置多个 id 标签),它在嵌套的映射配置时用于判断数据是否相同,当配置了 id 标签时,MyBatis 只需要逐条比较所有数据中 id 标签的字段是否相同即可。没有配置 id 标签时,MyBatis 会把 resultMap 中所有的字段进行比较,全部相同就合并,只要有一个字段不同就不合并。
在嵌套结果配置 id 属性时,如果查询语句中没有查询 id 属性配置的列,会导致 id 对应的值为 null。这种情况下,所有的 id 都相同,嵌套的集合中只有一条数据。所以在配置 id 列时,查询语句必须包括该列。
collection集合的嵌套查询
示例以自下而上的过程实现一个两层嵌套的功能,并且每一个方法都是独立可用,可以作为一个单独的查询。
(1)在 PrivilegeMapper.xml 中添加方法(privilegeMap 为sys_privilege 表的映射结果)
<resultMap id="privilegeMap" type="tk.mybatis.simple.model.SysPrivilege">
<id property="id" column="id"/>
<result property="privilegeName" column="privilege_name"/>
<result property="privilegeUrl" column="privilege_url"/>
</resultMap>
<select id="selectPrivilegeByRoleId" resultMap="privilegeMap">
select p.*
from sys_privilege p
inner join sys_role_privilege rp on rp.privilege_id = p.id
where rp.role_id = #{roleId}
</select>
(2)在 RoleMapper.xml 中配置映射和对应的查询方法(roleMap 为sys_role 表的映射结果)
<resultMap id="rolePrivilegeListMapSelect" type="tk.mybatis.simple.model.SysRole" extends="roleMap">
<collection property="privilegeList" column="{roleId=id}" fetchType="lazy"
select="tk.mybatis.simple.mapper.PrivilegeMapper.selectPrivilegeByRoleId"/>
</resultMap>
<select id="selectRoleByUserId" resultMap="rolePrivilegeListMapSelect">
select
r.id,
r.role_name,
r.enabled,
r.create_time,
r.create_by
from sys_role r
inner join sys_user_role ur on ur.role_id = r.id
where ur.user_id = #{userId}
</select>
column 属性配置的 {roleId=id} ,roleId 是方法selectPrivilegeByRoleId查询中的参数,id是当前查询selectRoleByUserId中查询出来的r.id。
(3)顶层,在 UserMapper.xml 中添加映射和查询
<resultMap id="userRoleListMapSelect" type="tk.mybatis.simple.model.SysUser" extends="userMap">
<collection property="roleList"
fetchType="lazy"
column="{userId=id}"
select="tk.mybatis.simple.mapper.RoleMapper.selectRoleByUserId"/>
</resultMap>
<select id="selectAllUserAndRolesSelect" resultMap="userRoleListMapSelect">
select
u.id,
u.user_name,
u.user_password,
u.user_info,
u.create_time
from sys_user u
where u.id = #{id}
</select>
同样,{userId=id}是将查询出来的 u.id 赋值给 userId,用于进行下一层查询。