概述
在关系型数据库中,经常要处理一对一、一对多的关系。例如在RBAC(Role-Based Access Control 基于角色的权限访问控制)权限系统中一个用户拥有多个角色,一个角色拥有多个权限这样复杂的嵌套关系。Mybatis可以轻松地解决这种复杂的关系。
数据库关系图
sys_user -- 用户表
sys_role -- 角色表
sys_user_role -- 用户和角色关联表
sys_perimssion -- 权限表
sys_role_perimssion -- 角色和权限关联表
一对一映射
假设一个用户只能拥有一个角色, 那么它们之间的关系就是一对一的关系:
/**
* 用户表实体
*/
@Data
public class User implements Serializable {
private Long id;
private String username;
private String password;
private Role role; // 一对一的关系
}
/**
* 角色表实体
*/
@Data
public class Role implements Serializable {
private Long id;
private String name;
}
/**
* 用户和角色关联表实体
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserRole implements Serializable {
private Long userId;
private Long roleId;
}
1. 自动映射实现一对一的映射:
自动映射就是通过别名让mybatis自动将值匹配到对应的属性上,如 user_type 对应 userType, 除了这种之外,mybatis还支持多层嵌套的属性映射,例如 role.role_type 映射到 role.roleType上。Mybatis会在User中查找role属性,如果存在role属性就创建role对象,然后在role对象中继续查找roleType,将role_type的值绑定到role对象的roleType属性上。
<!-- UserMapper.xml -->
<select id="findUserWithRoleById" resultType="com.ex.sample.model.User">
select
u.id,
u.username,
u.password,
r.id "role.id",
r.name "role.name",
r.remark "role.remark"
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
where u.id = #{id}
</select>
2. resultMap实现一对一的映射:
在result中的column的值必须与sql查询结果的列名一致, 为了避免不同表中存在重名的列,对role的列都增加了"r_"前缀, sql中为其设置了别名。
<!-- UserMapper.xml -->
<resultMap id="baseResultMap" type="com.ex.sample.model.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<!-- Role 的属性 -->
<result property="role.id" column="r_id"/>
<result property="role.name" column="r_name"/>
<result property="role.remark" column="r_remark"/>
</resultMap>
<select id="findUserWithRoleById" resultMap="baseResultMap">
select
u.id,
u.username,
u.password,
r.id r_id,
r.name r_name,
r.remark r_remark
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
where u.id = #{id}
</select>
3. resultMap的accociation标签实现一对一的映射:
在上面的代码的基础上,继续修改UserMapper.xml,增加如下代码:
<!--
UserMapper.xml
resultMap:
extends: 可以指定继承自某个resultMap, 那么对应的就拥有被继承者的所有字段
association:
property: 对应的实体类中的属性 (此处是User实体类中role属性)
columnPrefix: 配置前缀后, 在子标签配置的result的column时可以省略前缀 (多表查询时, sql返回结果中可能存在相同的列, 默认在重复的列后加1, 但我们可以为列指定别名来区分)
resultMap: 指定result映射, 也可以通过命名空间(e.g. com.ex.sample.mapper.RoleMapper)获得其他mapper.xml文件中的resultMap
-->
<resultMap id="userRoleMap" type="com.ex.sample.model.User" extends="baseResultMap">
<association property="role" columnPrefix="r_" resultMap="com.ex.sample.mapper.RoleMapper.baseResultMap"/>
</resultMap>
<select id="findUserWithRole" resultMap="userRoleMap">
select
u.id,
u.username,
u.password,
r.id r_id,
r.name r_name,
r.remark r_remark
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>
RoleMapper.xml 添加resultMap
<!-- RoleMapper.xml -->
<resultMap id="baseResultMap" type="com.ex.sample.model.Role">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="remark" column="remark"/>
</resultMap>
4. resultMap的association标签的嵌套查询:
嵌套查询是SQL通过多次查询得到的结果组合成一个对象,修改UserMapper.xml
<!--
UserMapper.xml
association:
column: 列名或别名, 将主查询中列的结果作为嵌套查询的参数,配置方式如 column={prop1=col1, prop2=col2}, prop1和prop2将作为嵌套查询的参数
fetchType: 数据加载方式, 可选值为lazy和eager, 分别为延迟加载和积极加载, 这个配置会覆盖全局的lazyLoadingEnabled配置
-->
<resultMap id="userRoleMap" type="com.ex.sample.model.User" extends="baseResultMap">
<association property="role" column="{id=role_id}" select="com.ex.sample.mapper.RoleMapper.findById" />
</resultMap>
<select id="findUserWithRoleById" resultMap="userRoleMap">
select
u.id,
u.username,
u.password,
ur.role_id
from sys_user u
inner join sys_user_role ur on u.id = ur.user_id
where id = #{id}
</select>
RoleMapper.xml 增加findById
<!-- RoleMapper.xml -->
<resultMap id="baseResultMap" type="com.ex.sample.model.Role">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="remark" column="remark"/>
</resultMap>
<select id="findById" resultMap="baseResultMap">
select * from sys_role where id = #{id}
</select>
一对多映射
一对多的关系, 主表中的一条数据会对应关联表中多条数据。如 一个用户拥有多个角色,每个角色又有多个权限的集合。
/**
* 用户表实体
*/
@Data
public class User implements Serializable {
private Long id;
private String username;
private String password;
private List<Role> roles; // 一对多的关系
}
1. collection集合的结果映射
集合的结果映射就是指通过一次SQL查询将所有的结果查询出来,然后通过配置的结果映射,将数据映射到不同的对象中去。
<!-- UserMapper.xml -->
<resultMap id="userRoleMap" type="com.ericx.sboot.model.User" extends="baseResultMap">
<collection property="roles" columnPrefix="r_" resultMap="com.ericx.sboot.mapper.RoleMapper.baseResultMap"/>
</resultMap>
<select id="findUserWithRoleById" resultMap="userRoleMap">
select
u.id,
u.username,
u.password,
r.id r_id,
r.name r_name,
r.remark r_remark
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
where id = #{id}
</select>
2. collection集合的嵌套查询
对于角色又拥有多个权限, 所以这里存在嵌套的功能。
/**
* 角色表实体
*/
@Data
public class Role {
private Long id;
private String name;
private String remark;
private List<Permission> permissions; // 一对多的关系
}
/**
* 权限表实体
*/
@Data
public class Permission {
private Long id;
private String name;
}
/**
* 角色和权限关联表实体
*/
@Data
public class RolePermission {
private Long roleId;
private Long permissionId;
}
<!-- PermissionMapper.xml -->
<resultMap id="baseResultMap" type="com.ex.sample.model.Permission">
<id property="id" column="id"/>
<result property="name" column="name"/>
</resultMap>
<select id="findPermissionsByRoleId" resultMap="baseResultMap">
select
p.id,
p.name,
form sys_permission p
inner join sys_role_permission rp on p.id = rp.permission_id
where rp.role_id = #{roleId}
</select>
RoleMapper.xml的配置和对应的查询方法,通过用户ID去查找对应的角色
<!-- RoleMapper.xml -->
<resultMap id="rolePermissionResultMap" extends="baseRequestMap" type="com.ex.sample.model.Role">
<collection property="permissions" column="{roleId=id}" select="com.ex.sample.mapper.PermissionMapper.findPermissionsByRoleId"/>
</resultMap>
<select id="findRolesByUserId" resultMap="rolePermissionResultMap">
select
r.id,
r.name,
r.remark
from sys_role r
inner join sys_user_role ur on r.id = ur.role_id
where ur.user_id = #{userId}
</select>
UserMapper.xml 中只查询对应的用户
<!-- UserMapper.xml -->
<resultMap id="userResultMap" type="com.ex.sample.model.User" extends="baseResultMap">
<collection property="roles" column="{userId=id}" select="com.ex.sample.mapper.RoleMapper.findRolesByUserId" fetchType="lazy"/>
</resultMap>
<select id="findUsers" resultMap="userResultMap">
select * from sys_user
</select>
最后
以上就是虚幻彩虹为你收集整理的Mybatis高级结果映射 [一对一, 一对多]的全部内容,希望文章能够帮你解决Mybatis高级结果映射 [一对一, 一对多]所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复