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 列时,查询语句必须包括该列。
示例以自下而上的过程实现一个两层嵌套的功能,并且每一个方法都是独立可用,可以作为一个单独的查询。
(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,用于进行下一层查询。