[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);
```