main方法 如何去掉http debug日志_在MyBatis中如何使用collection标签实现嵌套查询?...

# 需求升级

在上篇博客《一对多的关系,在MyBatis中如何映射?》中,我们实现了需求:根据用户id查询用户信息的同时获取用户拥有的角色。

因为角色可以拥有多个权限,所以本篇博客我们升级需求为:根据用户id查询用户信息的同时获取用户拥有的角色以及角色包含的权限。

# 实现方式

因为我们需要使用到权限表的映射,所以我们需要先在SysPrivilegeMapper.xml中添加如下映射:

<resultMap id="sysPrivilegeMap" type="com.zwwhnly.mybatisaction.model.SysPrivilege">    <id property="id" column="id"/>    <result property="privilegeName" column="privilege_name"/>    <result property="privilegeUrl" column="privilege_url"/>resultMap>

一般情况下不建议修改数据库表对应的实体类,所以这里我们新建类SysRoleExtend,让它继承SysRole类,并添加如下字段:

package com.zwwhnly.mybatisaction.model;import java.util.List;public class SysRoleExtend extends SysRole {    /**     * 角色包含的权限列表     */    private List sysPrivilegeList;    public ListgetSysPrivilegeList() {        return sysPrivilegeList;    }    public void setSysPrivilegeList(List sysPrivilegeList) {        this.sysPrivilegeList = sysPrivilegeList;    }}

然后在SysRoleMapper.xml中新建如下映射:

<resultMap id="rolePrivilegeListMap" extends="roleMap"           type="com.zwwhnly.mybatisaction.model.SysRoleExtend">    <collection property="sysPrivilegeList" columnPrefix="privilege_"                resultMap="com.zwwhnly.mybatisaction.mapper.SysPrivilegeMapper.sysPrivilegeMap"/>resultMap>

这里的roleMap我们在之前的博客中已经定义过,代码如下:

<resultMap id="roleMap" type="com.zwwhnly.mybatisaction.model.SysRole">    <id property="id" column="id"/>    <result property="roleName" column="role_name"/>    <result property="enabled" column="enabled"/>    <result property="createBy" column="create_by"/>    <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>resultMap>

com.zwwhnly.mybatisaction.mapper.SysPrivilegeMapper.sysPrivilegeMap就是我们刚刚在SysPrivilegeMapper.xml中新建的映射sysPrivilegeMap。

然后,需要将上篇博客中的userRoleListMap修改为:

<resultMap id="userRoleListMap" type="com.zwwhnly.mybatisaction.model.SysUserExtend" extends="sysUserMap">    <collection property="sysRoleList" columnPrefix="role_"                resultMap="com.zwwhnly.mybatisaction.mapper.SysRoleMapper.rolePrivilegeListMap">    collection>resultMap>

并且要修改上篇博客中id为selectAllUserAndRoles的select标签代码,因为要关联角色权限关系表和权限表:

    SELECT  u.id,            u.user_name,            u.user_password,            u.user_email,            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,            p.id role_privilege_id,            p.privilege_name role_privilege_privilege_name,            p.privilege_url role_privilege_privilege_url    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    INNER JOIN sys_role_privilege rp ON rp.role_id = r.id    INNER JOIN sys_privilege p ON p.id = rp.privilege_id

注意事项:

这里sys_privilege表的列名的别名前缀为role_privilege_,这是因为userRoleListMap中collection的columnPrefix属性为role_,并且指定的com.zwwhnly.mybatisaction.mapper.SysRoleMapper.rolePrivilegeListMap中collection的columnPrefix属性为privilege_,所以这里的前缀需要叠加,就变成了role_privilege_。

# 单元测试

修改上篇博客中建的测试方法testSelectAllUserAndRoles()代码为:

@Testpublic void testSelectAllUserAndRoles() {    SqlSession sqlSession = getSqlSession();    try {        SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);        List sysUserList = sysUserMapper.selectAllUserAndRoles();        System.out.println("用户数:" + sysUserList.size());        for (SysUserExtend sysUser : sysUserList) {            System.out.println("用户名:" + sysUser.getUserName());            for (SysRoleExtend sysRoleExtend : sysUser.getSysRoleList()) {                System.out.println("角色名:" + sysRoleExtend.getRoleName());                for (SysPrivilege sysPrivilege : sysRoleExtend.getSysPrivilegeList()) {                    System.out.println("权限名:" + sysPrivilege.getPrivilegeName());                }            }        }    } finally {        sqlSession.close();    }}

运行测试代码,测试通过,输出日志如下:

DEBUG [main] - ==> Preparing: SELECT u.id, u.user_name, u.user_password, u.user_email, 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, p.id role_privilege_id, p.privilege_name role_privilege_privilege_name, p.privilege_url role_privilege_privilege_url 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 INNER JOIN sys_role_privilege rp ON rp.role_id = r.id INNER JOIN sys_privilege p ON p.id = rp.privilege_idDEBUG [main] - ==> Parameters:TRACE [main] - <== Columns: id, user_name, user_password, user_email, create_time, role_id, role_role_name, role_enabled, role_create_by, role_create_time, role_privilege_id, role_privilege_privilege_name, role_privilege_privilege_urlTRACE [main] - <== Row: 1, admin, 123456, admin@mybatis.tk, 2019-06-27 18:21:07.0, 1, 管理员, 1, 1, 2019-06-27 18:21:12.0, 1, 用户管理, /usersTRACE [main] - <== Row: 1, admin, 123456, admin@mybatis.tk, 2019-06-27 18:21:07.0, 1, 管理员, 1, 1, 2019-06-27 18:21:12.0, 2, 角色管理, /rolesTRACE [main] - <== Row: 1, admin, 123456, admin@mybatis.tk, 2019-06-27 18:21:07.0, 1, 管理员, 1, 1, 2019-06-27 18:21:12.0, 3, 系统日志, /logsTRACE [main] - <== Row: 1, admin, 123456, admin@mybatis.tk, 2019-06-27 18:21:07.0, 2, 普通用户, 1, 1, 2019-06-27 18:21:12.0, 4, 人员维护, /personsTRACE [main] - <== Row: 1, admin, 123456, admin@mybatis.tk, 2019-06-27 18:21:07.0, 2, 普通用户, 1, 1, 2019-06-27 18:21:12.0, 5, 单位维护, /companiesTRACE [main] - <== Row: 1001, test, 123456, test@mybatis.tk, 2019-06-27 18:21:07.0, 2, 普通用户, 1, 1, 2019-06-27 18:21:12.0, 4, 人员维护, /personsTRACE [main] - <== Row: 1001, test, 123456, test@mybatis.tk, 2019-06-27 18:21:07.0, 2, 普通用户, 1, 1, 2019-06-27 18:21:12.0, 5, 单位维护, /companiesDEBUG [main] - <== Total: 7用户数:2用户名:admin角色名:管理员权限名:用户管理权限名:角色管理权限名:系统日志角色名:普通用户权限名:人员维护权限名:单位维护用户名:test角色名:普通用户权限名:人员维护权限名:单位维护

从日志可以看出,不仅查询出了用户拥有的角色信息,也查询出了角色包含的权限信息。

# 延迟加载

有的同学可能会说,返回的角色信息和权限信息我不一定用啊,每次关联这么多表查询一次数据库,好影响性能啊,能不能在我使用到角色信息即获取sysRoleList属性时再去数据库查询呢?答案当然是能,那么如何实现呢?

实现延迟加载需要使用collection标签的fetchType属性,该属性有lazy和eager两个值,分别代表延迟加载和积极加载。

由于需要根据角色Id获取该角色对应的所有权限信息,所以我们要先在SysPrivilegeMapper.xml中定义如下查询:

<select id="selectPrivilegeByRoleId" resultMap="sysPrivilegeMap">    SELECT p.*    FROM sys_privilege p    INNER JOIN sys_role_privilege rp ON rp.privilege_id = p.id    WHERE rp.role_id = #{roleId}select>

然后在SysRoleMapper.xml中添加如下查询:

<resultMap id="rolePrivilegeListMapSelect" extends="roleMap"           type="com.zwwhnly.mybatisaction.model.SysRoleExtend">    <collection property="sysPrivilegeList" fetchType="lazy"                column="{roleId=id}"                select="com.zwwhnly.mybatisaction.mapper.SysPrivilegeMapper.selectPrivilegeByRoleId"/>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。

然后在SysUserMapper.xml中添加如下查询:

<resultMap id="userRoleListMapSelect" extends="sysUserMap"           type="com.zwwhnly.mybatisaction.model.SysUserExtend">    <collection property="sysRoleList" fetchType="lazy"                select="com.zwwhnly.mybatisaction.mapper.SysRoleMapper.selectRoleByUserId"                column="{userId=id}"/>resultMap>
<select id="selectAllUserAndRolesSelect" resultMap="userRoleListMapSelect">    SELECT          u.id,          u.user_name,          u.user_password,          u.user_email,          u.create_time    FROM sys_user u    WHERE u.id = #{id}select>

上面的column="{userId=id}"中,userId指的是select指定的方法selectRoleByUserId的参数,id指的是查询selectAllUserAndRolesSelect中查询出的用户id。

然后,在SysUserMapper接口中,添加如下方法:

/** * 通过嵌套查询获取指定用户的信息以及用户的角色和权限信息 * * @param id * @return */SysUserExtend selectAllUserAndRolesSelect(Long id);

最后,在SysUserMapperTest类中添加如下测试方法:

@Testpublic void testSelectAllUserAndRolesSelect() {    SqlSession sqlSession = getSqlSession();    try {        SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);        SysUserExtend sysUserExtend = sysUserMapper.selectAllUserAndRolesSelect(1L);        System.out.println("用户名:" + sysUserExtend.getUserName());        for (SysRoleExtend sysRoleExtend : sysUserExtend.getSysRoleList()) {            System.out.println("角色名:" + sysRoleExtend.getRoleName());            for (SysPrivilege sysPrivilege : sysRoleExtend.getSysPrivilegeList()) {                System.out.println("权限名:" + sysPrivilege.getPrivilegeName());            }        }    } finally {        sqlSession.close();    }}

运行测试方法,输出日志如下:

DEBUG [main] - ==> Preparing: SELECT u.id, u.user_name, u.user_password, u.user_email, u.create_time FROM sys_user u WHERE u.id = ?DEBUG [main] - ==> Parameters: 1(Long)TRACE [main] - <== Columns: id, user_name, user_password, user_email, create_timeTRACE [main] - <== Row: 1, admin, 123456, admin@mybatis.tk, 2019-06-27 18:21:07.0DEBUG [main] - <== Total: 1用户名:adminDEBUG [main] - ==> Preparing: 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 = ?DEBUG [main] - ==> Parameters: 1(Long)TRACE [main] - <== Columns: id, role_name, enabled, create_by, create_timeTRACE [main] - <== Row: 1, 管理员, 1, 1, 2019-06-27 18:21:12.0TRACE [main] - <== Row: 2, 普通用户, 1, 1, 2019-06-27 18:21:12.0DEBUG [main] - <== Total: 2角色名:管理员DEBUG [main] - ==> Preparing: SELECT p.* FROM sys_privilege p INNER JOIN sys_role_privilege rp ON rp.privilege_id = p.id WHERE rp.role_id = ?DEBUG [main] - ==> Parameters: 1(Long)TRACE [main] - <== Columns: id, privilege_name, privilege_urlTRACE [main] - <== Row: 1, 用户管理, /usersTRACE [main] - <== Row: 2, 角色管理, /rolesTRACE [main] - <== Row: 3, 系统日志, /logsDEBUG [main] - <== Total: 3权限名:用户管理权限名:角色管理权限名:系统日志角色名:普通用户DEBUG [main] - ==> Preparing: SELECT p.* FROM sys_privilege p INNER JOIN sys_role_privilege rp ON rp.privilege_id = p.id WHERE rp.role_id = ?DEBUG [main] - ==> Parameters: 2(Long)TRACE [main] - <== Columns: id, privilege_name, privilege_urlTRACE [main] - <== Row: 4, 人员维护, /personsTRACE [main] - <== Row: 5, 单位维护, /companiesDEBUG [main] - <== Total: 2权限名:人员维护权限名:单位维护

仔细分析上面的日志,会发现只有在使用到了角色信息和权限信息时,才执行了对应的数据库查询。

需要注意的是,延迟加载依赖于MyBatis全局配置中的aggressiveLazyLoading,在之前的博客讲解association标签时,我们已经将其配置为了false,所以这里的执行结果符合我们的预期:

<settings>        <setting name="aggressiveLazyLoading" value="false"/>settings>

关于该参数的详细讲解,请查看MyBatis从入门到精通(十):使用association标签实现嵌套查询。

# 总结

使用collection标签实现嵌套查询,用到的属性总结如下:

1)select:另一个映射查询的id,MyBatis会额外执行这个查询获取嵌套对象的结果。

2)column:将主查询中列的结果作为嵌套查询的参数,配置方式如column="{prop1=col1,prop2=col2}",prop1和prop2将作为嵌套查询的参数。

3)fetchType:数据加载方式,可选值为lazy和eager,分别为延迟加载和积极加载。

4)如果要使用延迟加载,除了将fetchType设置为lazy,还需要注意全局配置aggressiveLazyLoading的值应该为false。这个参数在3.4.5版本之前默认值为ture,从3.4.5版本开始默认值改为false。

5)MyBatis提供的lazyLoadTriggerMethods参数,支持在触发某方法时直接触发延迟加载属性的查询,如equals()方法。

#  源码及参考

  • 源码地址:https://github.com/zwwhnly/mybatis-action.git,欢迎下载。

  • 刘增辉《MyBatis从入门到精通》

作者:申城异乡人

来源:https://www.cnblogs.com/zwwhnly/p/11201185.html

 往期推荐 

?

  • 一个小需求,能够做到月活跃用户5000万,就是真牛逼!
  • 如何在面试中介绍自己的项目经验?
  • 百度面试官:如果叫你设计一个短链接系统,你会从那些方面来提高性能呢?

6db08e30888e6dcd39e4c0ed864b7e15.png

790042521d84f6f22f62452c1c80d153.gif  

点击

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值