1.collection集合的嵌套结果映射
1.1 基本使用
与association
类似,集合的嵌套结果映射就是通过一次SQL查询将所有的结果查询出来,然后通过配置的结果映射,将数据映射到不同的对象中去。
准备数据
一个用户有多个角色,一个角色又有多种权限
//用户实体类
public class User {
private Integer id;
private String username;
private String password;
//一对多:一个用户对应多种角色
private List<Role> role;
}
//角色类
public class Role {
private Integer id;
private String role;
private Date createDate;
}
如何查询出全部用户及其角色
UserMapper.xml
<resultMap id="userRoleListMap" type="com.example.pojo.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<collection property="roleList" columnPrefix="role_"
javaType="com.example.pojo.Role">
<id property="id" column="id"/>
<result property="role" column="role"/>
<result property="createDate" column="create_date"/>
</collection>
</resultMap>
👇
<resultMap id="userRoleListMap" type="com.example.pojo.User" extends="userMap">
<collection property="roleList" columnPrefix="role_"
ofType="com.example.pojo.Role">
<id property="id" column="id"/>
<result property="role" column="role"/>
<result property="createDate" column="create_date"/>
</collection>
</resultMap>
👇
<resultMap id="userRoleListMap" type="com.example.pojo.User" extends="userMap">
<collection property="roleList" columnPrefix="role_"
ofType="com.example.pojo.Role" resultMap="com.example.mapper.RoleMapper.roleMapper"/>
</resultMap>
select
<select id="selectAllUserAndRoles" resultMap="userRoleListMap">
select user.id, username, password, r.id "role_id", r.role "role_role", r.create_date "role_create_date"
from user
inner join user_role_merage urm on user.id = urm.user_id
inner join role r on urm.role_id = r.id
</select>
测试成功
踩坑
1.2 一对多中MyBatis的处理规则
MyBatis在处理结果的时候,会判断结果是否相同,如果是相同的结果,则只会保留第一个结果,所以这个问题的关键点是MyBatis如何判断结果是否相同。
最简单的情况是在映射配置中有一个id
标签,例如:
<id property="id" column="id" />
我们对id
的理解是:它配置的字段为表的主键(联合主键时可以配置多个id标签)。id的唯一作用就是在嵌套的配置映射中判断数据是否相同。
由此一来,上面的查询就不难理解了,因为其id相同,所以它们属于同一个用户
在RBAC中,除了一个用户对应多个角色外,每一个角色还会对应多种权限,所以在现有的例子的基础上再加一级,获取角色对应的所有权限。
@Data
public class Privilege {
private Integer id;
private String name;
private String url;
}
UserMapper.xml
<resultMap id="userRoleListMap" type="com.example.pojo.User" extends="userMap">
<collection property="roleList" columnPrefix="role_"
ofType="com.example.pojo.Role"
resultMap="com.example.mapper.RoleMapper.rolePrivilegeListMap"/>
</resultMap>
<select id="selectAllUserAndRoles" resultMap="userRoleListMap">
select user.id,
username,
password,
r.id "role_id",
r.role "role_role",
r.create_date "role_create_date",
privilege.id "role_privilege_id",
privilege.name "role_privilege_name",
privilege.url "role_privilege_url"
from user
inner join user_role_merage urm on user.id = urm.user_id
inner join role r on urm.role_id = r.id
left join role_privilege_merage rpm on r.id = rpm.role_id
left join privilege on privilege.id = rpm.pri_id;
</select>
RoleMapper.xml
<resultMap id="roleMapper" type="com.example.pojo.Role">
<id property="id" column="id"/>
<result property="role" column="role"/>
<result property="createDate" column="create_date"/>
</resultMap>
<resultMap id="rolePrivilegeListMap" type="com.example.pojo.Role"
extends="roleMapper">
<collection property="privilegeList" ofType="com.example.pojo.Privilege"
columnPrefix="privilege_"
resultMap="com.example.mapper.PrivilegeMapper.BaseResultMap"/>
</resultMap>
PrivilegeMapper.xml
<resultMap id="BaseResultMap" type="com.example.pojo.Privilege">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="url" jdbcType="VARCHAR" property="url" />
</resultMap>
测试成功
注意:因为privilege嵌套在rolePrivilegeListMap,而rolePrivilegeListMap的前缀是“role_”,所以BaseResultMap中的前缀就变成了“role_privilege_”。前缀一定不要写错。
2.collection集合的嵌套查询
使用嵌套查询来完成嵌套结果映射的功能。
PrivilegeMapper.xml
<select id="selectPrivilegeByRoleId" resultMap="BaseResultMap">
select privilege.*
from privilege
inner join role_privilege_merage on privilege.id = role_privilege_merage.pri_id
where role_id = #{roleId};
</select>
RoleMapper.xml
<resultMap id="rolePrivilegeListMapSelect" type="com.example.pojo.Role" extends="roleMapper">
<collection property="privilegeList" select="com.example.mapper.PrivilegeMapper.selectPrivilegeByRoleId"
column="{roleId=id}"/>
</resultMap>
<select id="selectRoleByUserId" resultMap="rolePrivilegeListMapSelect">
select role.*
from role
inner join user_role_merage urm on role.id = urm.role_id
where user_id = #{userId};
</select>
UserMapper.xml
<resultMap id="userRoleListMap" type="com.example.pojo.User" extends="userMap">
<collection property="roleList" select="com.example.mapper.RoleMapper.selectRoleByUserId"
column="{userId=id}"/>
</resultMap>
<select id="selectAllUserAndRolesSlect" resultMap="userRoleListMap">
select *
from user
where user.id = #{id};
</select>
测试成功