[TOC]
*****
# 6.1.2 一对多映射
**推荐使用一对多的嵌套查询映射,不要使用嵌套结果**
## 6.1.2.1 collection集合的嵌套结果映射
一个系统用户拥有多个系统角色
**1 在SysUser.java中增加**
```
package tk.mybatis.simple.model;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* 用户表
*/
public class SysUser implements Serializable {
private static final long serialVersionUID = -328602757171077630L;
/**
* 用户的角色集合
*/
private List<SysRole> roleList;
public List<SysRole> getRoleList() {
return roleList;
}
public void setRoleList(List<SysRole> roleList) {
this.roleList = roleList;
}
}
```
**2 在UserMapper.xml中**
```
<resultMap id="userRoleListMap" extends="userMap" type="tk.mybatis.simple.model.SysUser">
<collection property="roleList" columnPrefix="role_" resultMap="tk.mybatis.simple.mapper.RoleMapper.roleMap"/>
</resultMap>
```
**3 在UserMapper.xml中**
查询所有用户及其对应的角色
```
<select id="selectAllUserAndRoles" resultMap="userRoleListMap">
select
u.id,
u.user_name,
u.user_password,
u.user_email,
u.user_info,
u.head_img,
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 ur.role_id = r.id
</select>
```
**4 在UserMapper接口中增加如下的对应方法**
```
* 获取所有的用户以及对应的所有角色
*
* @return
*/
List<SysUser> selectAllUserAndRoles();
```
MyBatis 在处理结果的时候, 会判断结果是否相同, 如果是相同的
结果, 则只会保留第一个结果, 所以这个问题的关键点就是 MyBatis 如
何判断结果是否相同。 MyBatis 判断结果是否相同时, 最简单的情况就
是在映射配置中至少有一个id标签, 在userMap中配置如下。
**<id property="id" column="id"/>**
我们对 id(构造方法中为 idArg) 的理解一般是, 它配置的字段为
表的主键(联合主键时可以配置多个id标签) , 因为MyBatis的
resultMap只用于配置结果如何映射, 并不知道这个表具体如何。 id的唯
一作用就是在嵌套的映射配置时判断数据是否相同, 当配置id标签时,
MyBatis只需要逐条比较所有数据中id标签配置的字段值是否相同即
可。 在配置嵌套结果查询时, 配置id标签可以提高处理效率。
这样一来, 上面的查询就不难理解了。 因为前两条数据的userMap
部分的id相同, 所以它们属于同一个用户, 因此这条数据会合并到同一
个用户中
## 6.1.2.2 collection集合的嵌套查询
示例 : 通过角色id获取该角色对应的所有权限信息
**1 在PrivilegeMapper.xml中添加如下方法**
通过角色id获取该角色对应的所有权限信息
```
<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 role_id = #{roleId}
</select>
```
**2 在RoleMapper.xml中配置映射和对应的查询方法**
通过系统用户id查询该用户对应的所有系统角色
```
<resultMap id="rolePrivilegeListMapSelect" extends="roleMap" type="tk.mybatis.simple.model.SysRole">
<collection property="privilegeList"
fetchType="lazy"
select="tk.mybatis.simple.mapper.PrivilegeMapper.selectPrivilegeByRoleId"
column="{roleId=id}"/>
</resultMap>
<select id="selectRoleByUserId" resultMap="rolePrivilegeListMapSelect">
select
r.id,
r.role_name,
r.enabled,
r.create_by,
r.create_time
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 是select 指定方法selectPrivilegeByRoleId查询中的参数, id是当前查询 selectRoleByUserId中查询出的角色 id。
**3 在UserMapper.xml中添加如下映射和查询**
通过系统用户id查出对应系统用户和所有角色
```
<resultMap id="userRoleListMapSelect" extends="userMap" type="tk.mybatis.simple.model.SysUser">
<collection property="roleList"
fetchType="lazy"
select="tk.mybatis.simple.mapper.RoleMapper.selectRoleByUserId"
column="{userId=id}"/>
</resultMap>
<select id="selectAllUserAndRolesSelect" resultMap="userRoleListMapSelect">
select
u.id,
u.user_name,
u.user_password,
u.user_email,
u.user_info,
u.head_img,
u.create_time
from sys_user u
where u.id = #{id}
</select>
```
**4 在UserMapper.xml中增加方法**
通过嵌套查询获取指定用户的信息,以及用户的角色和权限信息
```
SysUser selectAllUserAndRolesSelect(Long id);
```