mybatis学习7

一、一对多映射:
表结构参考mybatis学习2
1、一个用户对应多个角色
UserMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.linst.mapper.UserMapper">

    <resultMap id="userMap" type="cn.linst.model.SysUser">
        <id property="id" column="id" />
        <result property="userName" column="user_name" />
        <result property="userPassword" column="user_password" />
        <result property="userEmail" column="user_email" />
        <result property="userInfo" column="user_info" />
        <result property="headImg" column="head_img" jdbcType="BLOB" />
        <result property="createTime" column="create_time" jdbcType="TIMESTAMP" />
    </resultMap>
    
    <resultMap id="userRoleListMap" extends="userMap" type="cn.linst.model.SysUser">
        <collection property="roleList" columnPrefix="role_" resultMap="cn.linst.mapper.RoleMapper.roleMap">
        </collection>
    </resultMap>


    <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 ur.user_id = u.id
      inner join sys_role r on r.id = ur.role_id
    </select>
    
</mapper>

RoleMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.linst.mapper.RoleMapper">


    <resultMap id="roleMap" type="cn.linst.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>
    
</mapper>

UserMapper:

 package cn.linst.mapper;

import cn.linst.model.SysRole;
import cn.linst.model.SysUser;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface UserMapper {
    
    
 	/**
     * 获取所有的用户以及对应的所有角色
     * @return
     */
    List<SysUser> selectAllUserAndRoles();
    
}    

UserMapperTest:

package cn.linst;


import cn.linst.mapper.UserMapper;
import cn.linst.model.SysRole;
import cn.linst.model.SysUser;
import org.apache.ibatis.session.SqlSession;
import org.junit.Assert;
import org.junit.Test;

import java.util.*;

public class UserMapperTest extends BaseMapperTest {
    
       
    @Test
    public void testSelectUserAndRoles() {
    
    
        // 获取sqlSession
        SqlSession sqlSession = getSqlSession();
        try {
    
    
            // 获 UserMapper 接口
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            // 这里使用只有一个角色的用户( id=1OO1L)
            List<SysUser> userList = userMapper.selectAllUserAndRoles();

            System.out.println("用户数:" + userList.size());
            for (SysUser user : userList) {
    
    
                System.out.println("用户名" + user.getUserName());
                for (SysRole role: user.getRoleList()) {
    
    
                    System.out.println("角色名" + role.getRoleName());
                }
            }
        } finally {
    
    
            // 不要忘记关闭 sqlSession
            sqlSession.close();
        }
    }
}

BaseMapperTest:

package cn.linst;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.BeforeClass;

import java.io.IOException;
import java.io.Reader;



public class BaseMapperTest {
    
    

    private static SqlSessionFactory sqlSessionFactory;

    @BeforeClass
    public static void init () {
    
    
        try {
    
    
            Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            reader.close();
        } catch (IOException ex) {
    
    
            ex.printStackTrace();
        }
    }

    public SqlSession getSqlSession() {
    
    
        return sqlSessionFactory.openSession();
    }
}
DEBUG [main] - ==>  Preparing: 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 ur.user_id = u.id inner join sys_role r on r.id = ur.role_id 
DEBUG [main] - ==> Parameters: 
TRACE [main] - <==    Columns: id, user_name, user_password, user_email, user_info, head_img, create_time, role_id, role_role_name, role_enabled, role_create_by, role_create_time
TRACE [main] - <==        Row: 1, admin, 123456, admin_test@admin_test.email, <<BLOB>>, <<BLOB>>, 2020-01-01 01:11:12.0, 1, 管理员, 1, 1, 2020-01-01 17:02:14.0
TRACE [main] - <==        Row: 1, admin, 123456, admin_test@admin_test.email, <<BLOB>>, <<BLOB>>, 2020-02-01 01:11:12.0, 2, 普通用户, 1, 1, 2020-02-01 17:02:34.0
TRACE [main] - <==        Row: 1001, test, 123456, test@testemail, <<BLOB>>, <<BLOB>>, 2020-01-01 00:00:00.0, 2, 普通用户, 1, 1, 2020-02-01 17:02:34.0
DEBUG [main] - <==      Total: 3
用户数:2
用户名admin
角色名管理员
角色名普通用户
用户名test
角色名普通用户

通过日志可以看到, SQL 执行的结果数有3 条,后面输出的用户数是2 ,也就是说本来查询出的 3条结果经过 MyBatis 的collection 数据的处理后,变成了两条。
MyBatis 在处理结果的时候, 会判断结果是否相同 ,如果是相同的结果 ,则只会保留第1个结果。

就是在映射配置中至少有一个 id 标签。它配置的字段为表的主键(联合主键时可以配置多个 id 标签),

<id property="id" column="id" />

id 的唯一作用就是在嵌套的映射配置 判断数据是否相同,当配置工 标签时, MyBatis 只需要逐条比较所有数据中 id 标签配置的字段值是否相同即可。
因为前两条数据 userMap 部分的相同, 所以它们属于同一个用户,因此这条数据会合并到同一个用户中。

如:为了验证,将userMap的 id 设置为userPassword。
UserMapper.xml:

   <resultMap id="userMap" type="cn.linst.model.SysUser">
        <id property="userPassword" column="user_password" />
        <result property="userName" column="user_name" />
        <result property="id" column="id" />
        <result property="userEmail" column="user_email" />
        <result property="userInfo" column="user_info" />
        <result property="headImg" column="head_img" jdbcType="BLOB" />
        <result property="createTime" column="create_time" jdbcType="TIMESTAMP" />
    </resultMap>

假设用户密码都是123456,那么查询出来的3条数据,就会合并为一条。

运行测试,打印结果:

扫描二维码关注公众号,回复: 12813354 查看本文章
DEBUG [main] - ==>  Preparing: 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 ur.user_id = u.id inner join sys_role r on r.id = ur.role_id 
DEBUG [main] - ==> Parameters: 
TRACE [main] - <==    Columns: id, user_name, user_password, user_email, user_info, head_img, create_time, role_id, role_role_name, role_enabled, role_create_by, role_create_time
TRACE [main] - <==        Row: 1, admin, 123456, admin_test@admin_test.email, <<BLOB>>, <<BLOB>>, 2020-01-01 01:11:12.0, 1, 管理员, 1, 1, 2020-02-01 17:02:14.0
TRACE [main] - <==        Row: 1, admin, 123456, admin_test@admin_test.email, <<BLOB>>, <<BLOB>>, 2020-01-01 01:11:12.0, 2, 普通用户, 1, 1, 2020-02-01 17:02:34.0
TRACE [main] - <==        Row: 1001, test, 123456, test@testemail, <<BLOB>>, <<BLOB>>, 2020-01-01 00:00:00.0, 2, 普通用户, 1, 1, 2020-02-01 17:02:34.0
DEBUG [main] - <==      Total: 3
用户数:1
用户名admin
角色名管理员
角色名普通用户

用户信息保留的是第1条数据的信息, 因此用户名是 admin。
前面将 id 标签配置为 userPassword 时,最后的结果少了1个角色,这是因为 MyBatis 会对嵌套查询的每一级对象都进行属性 比较。

当没有配置 id 时, mybatis 就会把 resultMap 中配置的所有字段进行比较,如果所有的字段的值都相同就合并,只要有1个字段值不同,就不合井。
注:

在嵌套结果配直 id 属性时 如果查询语句中没有查询 id 属性配直的列,就会导 id对应的值为 null 这种情况下,所有值的 id 都相同,
因此会使嵌套的集合中只有一条数据,所以在配置id时,查询语句中必须包含该列。

2、一个角色对应多个权限

RoleMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.linst.mapper.RoleMapper">

    <resultMap id="rolePrivilegeListMap" extends="roleMap" type="cn.linst.model.SysRole">
        <collection property="privilegeList" columnPrefix="privilege_" resultMap="cn.linst.mapper.PrivilegeMapper.privilegeMap"/>
    </resultMap>
    
    <select id="selectAllRoleAndPrivileges" resultMap="rolePrivilegeListMap">
      select
        r.id role_id,
        r.role_name role_name,
        r.enabled enabled,
        r.create_by create_by,
        r.create_time create_time,
        p.id privilege_id,
        p.privilege_name privilege_privilege_name,
        p.privilege_url privilege_privilege_url
      from sys_role r
      inner join sys_role_privilege rp on rp.role_id = r.id
      inner join sys_privilege p on p.id = rp.privilege_id
    </select>
</mapper>

PrivilegeMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.linst.mapper.PrivilegeMapper">
    <resultMap id="privilegeMap" type="cn.linst.model.SysPrivilege">
        <id property="id" column="id"/>
        <result property="privilegeUrl" column="privilege_url" />
        <result property="privilegeName" column="privilege_name"/>
    </resultMap>


</mapper>

RoleMapper.xml:

package cn.linst.mapper;


import cn.linst.model.SysPrivilege;
import cn.linst.model.SysRole;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface RoleMapper {
    
    

    List<SysRole> selectAllRoleAndPrivileges() ;
}

SysRole:

package cn.linst.model;

import lombok.Getter;
import lombok.Setter;

import java.util.Date;
import java.util.List;

@Setter
@Getter
public class SysRole {
    
    

    private Long id;

    private String roleName;

    private  Integer enabled;

    private Long createBy;

    private Date createTime;

    private SysUser user;

    /**
     * 角色包含的权限列表
     */
    List<SysPrivilege> privilegeList;
}

package cn.linst.model;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class SysPrivilege {
    
    

    private Long id;

    private String  privilegeName;

    private String privilegeUrl;

}

SysRolePrivilege:

package cn.linst.model;


import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class SysRolePrivilege {
    
    
    private Long roleId;

    private Long privilegeId;
}

测试方法:

package cn.linst;


import cn.linst.mapper.RoleMapper;
import cn.linst.model.SysPrivilege;
import cn.linst.model.SysRole;
import org.apache.ibatis.session.SqlSession;
import org.junit.Assert;
import org.junit.Test;

import java.util.List;

public class RoleMapperTest extends BaseMapperTest{
    
    
	@Test
	public void testSelectAllRoleAndPrivileges() {
    
    
	    // 获取sqlSession
	    SqlSession sqlSession = getSqlSession();
	    try {
    
    
	        // 获取 RoleMapper 接口
	        RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
	        List<SysRole> roleList = roleMapper.selectAllRoleAndPrivileges();
	
	        for (SysRole role: roleList) {
    
    
	            System.out.println("角色名:" + role.getRoleName());
	            for (SysPrivilege privilege : role.getPrivilegeList()) {
    
    
	                System.out.println("权限:" + privilege.getPrivilegeName());
	            }
	            System.out.println("==========");
	        }
	    } finally {
    
    
	        // 不要忘记关闭 sqlSession
	        sqlSession.close();
	    }
	}
}

运行结果:

DEBUG [main] - ==>  Preparing: select r.id role_id, r.role_name role_name, r.enabled enabled, r.create_by create_by, r.create_time create_time, p.id privilege_id, p.privilege_name privilege_privilege_name, p.privilege_url privilege_privilege_url from sys_role r inner join sys_role_privilege rp on rp.role_id = r.id inner join sys_privilege p on p.id = rp.privilege_id 

角色名:管理员
权限:用户管理
==========
角色名:管理员
权限:系统日志
==========
角色名:管理员
权限:角色管理
==========
角色名:普通用户
权限:人员维护
==========
角色名:普通用户
权限:单位维护
==========

3、一个用户对应多个权限(一个用户有多个角色,一个角色有多个权限。)

PrivilegeMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.linst.mapper.PrivilegeMapper">
    <resultMap id="privilegeMap" type="cn.linst.model.SysPrivilege">
        <id property="id" column="id"/>
        <result property="privilegeUrl" column="privilege_url" />
        <result property="privilegeName" column="privilege_name"/>
    </resultMap>


</mapper>

SysUser:

package cn.linst.model;

import lombok.Getter;
import lombok.Setter;

import java.util.Date;
import java.util.List;


@Getter
@Setter
public class SysUser {
    
    

    private Long id;

    private String userName;

    private String userPassword;

    private String userEmail;

    private String userInfo;

    // byte[]这个类型一般对应数据库中的 BLOB、LONGVARBINARY 以及和二进制流有关的字段类型
    private byte[] headImg;

    private Date createTime;


    /**
     * 用户角色
     */
    private SysRole role;


    /**
     * 用户的角色集合
     */
    private List<SysRole> roleList;
}

SysRole:

package cn.linst.model;

import lombok.Getter;
import lombok.Setter;

import java.util.Date;
import java.util.List;

@Setter
@Getter
public class SysRole {
    
    

    private Long id;

    private String roleName;

    private  Integer enabled;

    private Long createBy;

    private Date createTime;

    private SysUser user;

    /**
     * 角色包含的权限列表
     */
    List<SysPrivilege> privilegeList;
}

RoleMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.linst.mapper.RoleMapper">

    <resultMap id="rolePrivilegeListMap" extends="roleMap" type="cn.linst.model.SysRole">
        <collection property="privilegeList" columnPrefix="privilege_" resultMap="cn.linst.mapper.PrivilegeMapper.privilegeMap"/>
    </resultMap>

    <resultMap id="roleMap" type="cn.linst.model.SysRole">
        <result property="id" column="role_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>
</mapper>

UserMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.linst.mapper.UserMapper">
    <resultMap id="userMap" type="cn.linst.model.SysUser">
        <id property="id" column="id" />
        <result property="userName" column="user_name" />
        <result property="userPassword" column="user_password" />
        <result property="userEmail" column="user_email" />
        <result property="userInfo" column="user_info" />
        <result property="headImg" column="head_img" jdbcType="BLOB" />
        <result property="createTime" column="create_time" jdbcType="TIMESTAMP" />
    </resultMap>

    <resultMap id="userRoleListMap" extends="userMap" type="cn.linst.model.SysUser">
        <collection property="roleList" columnPrefix="role_" resultMap="cn.linst.mapper.RoleMapper.rolePrivilegeListMap">
        </collection>
    </resultMap>

	 <select id="selectAllUserAndRolesAndPrivilege" 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,
	    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 ur.user_id = u.id
	  inner join sys_role r on r.id = ur.role_id
	  inner join sys_role_privilege rp on rp.role_id = r.id
	  inner join sys_privilege p on p.id = rp.privilege_id
	</select>
</mapper>

UserMapper:

package cn.linst.mapper;

import cn.linst.model.SysRole;
import cn.linst.model.SysUser;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface UserMapper {
    
    
	List<SysUser> selectAllUserAndRolesAndPrivilege();
}   

UserMapperTest:

package cn.linst;

import cn.linst.mapper.UserMapper;
import cn.linst.model.SysPrivilege;
import cn.linst.model.SysRole;
import cn.linst.model.SysUser;
import org.apache.ibatis.session.SqlSession;
import org.junit.Assert;
import org.junit.Test;

import java.util.*;

public class UserMapperTest extends BaseMapperTest {
    
    
    @Test
    public void testSelectUserAndRolesAndPrivilege() {
    
    
        // 获取sqlSession
        SqlSession sqlSession = getSqlSession();
        try {
    
    
            // 获 UserMapper 接口
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
          
            List<SysUser> userList = userMapper.selectAllUserAndRolesAndPrivilege();

            System.out.println("用户数:" + userList.size());
            for (SysUser user : userList) {
    
    
                System.out.println("用户名" + user.getUserName());
                for (SysRole role: user.getRoleList()) {
    
    
                    System.out.println("角色名" + role.getRoleName());
                    for (SysPrivilege privilege : role.getPrivilegeList()) {
    
    
                        System.out.println("权限" + privilege.getPrivilegeName());
                    }
                }
            }
        } finally {
    
    
            // 不要忘记关闭 sqlSession
            sqlSession.close();
        }
    }
}

运行结果:

DEBUG [main] - ==>  Preparing: 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, 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 ur.user_id = u.id inner join sys_role r on r.id = ur.role_id inner join sys_role_privilege rp on rp.role_id = r.id inner join sys_privilege p on p.id = rp.privilege_id 

用户数:2
用户名admin
角色名管理员
权限用户管理
权限系统日志
权限角色管理
角色名普通用户
权限人员维护
权限单位维护
用户名test
角色名普通用户
权限人员维护
权限单位维护

4、collection 集合的嵌套查询
PrivilegeMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.linst.mapper.PrivilegeMapper">
    <resultMap id="privilegeMap" type="cn.linst.model.SysPrivilege">
        <id property="id" column="id"/>
        <result property="privilegeUrl" column="privilege_url" />
        <result property="privilegeName" column="privilege_name"/>
    </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>
</mapper>

RoleMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.linst.mapper.RoleMapper">

    <resultMap id="roleMap" type="cn.linst.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>

    <resultMap id="rolePrivilegeListMapSelect" extends="roleMap" type="cn.linst.model.SysRole" >
        <collection property="privilegeList" fetchType="lazy" column="{roleId=id}" select="cn.linst.mapper.PrivilegeMapper.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>
    
</mapper>
column 属性配置的{
    
    roleId=id}, roleId 是select 指定方法selectPrivilegeByRoleId 查询中的参数,
id 是当前查询 selectRoleByUserId 中查询出的角色id。selectRoleByUserId 是一个只有一层嵌套的一对多映射配置,
通过调用PrivilegeMapper 的selectPrivilegeByRoleId 方法,这样就实现了嵌套查询的功能

UserMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.linst.mapper.UserMapper">
	<resultMap id="userRoleListMapSelect" extends="userMap" type="cn.linst.model.SysUser" >
        <collection property="roleList"
            fetchType="lazy"
            select="cn.linst.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>
</mapper>
collection 的属性 column 配置为{userId=id} ,将当前查询用户中的id赋值给 userId ,
使用 userId 作为参数再进行 selectRoleByUserId 查询。因为所有嵌套查询都配置为延迟加载,因此不存在 N+l 的问题。

UserMapper:

package cn.linst.mapper;

import cn.linst.model.SysRole;
import cn.linst.model.SysUser;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface UserMapper {
    
    
	 /**
	  * 通过嵌套查询获取指定用户的信息以及用户的角 色和权限信息
	  *
	  */
	 SysUser selectAllUserAndRolesSelect(Long id);
}

测试,UserMapperTest:

package cn.linst;


import cn.linst.mapper.RoleMapper;
import cn.linst.mapper.UserMapper;
import cn.linst.model.SysPrivilege;
import cn.linst.model.SysRole;
import cn.linst.model.SysUser;
import org.apache.ibatis.session.SqlSession;
import org.junit.Assert;
import org.junit.Test;

import java.util.*;

public class UserMapperTest extends BaseMapperTest {
    
    
  @Test
    public void testSelectAllUserAndRolesSelect() {
    
    
        // 获取sqlSession
        SqlSession sqlSession = getSqlSession();
        try {
    
    
            // 获 UserMapper 接口
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            SysUser user = userMapper.selectAllUserAndRolesSelect(1L);
            System.out.println("用户名" + user.getUserName());
            for (SysRole role: user.getRoleList()) {
    
    
                System.out.println("角色名" + role.getRoleName());
                for (SysPrivilege privilege : role.getPrivilegeList()) {
    
    
                    System.out.println("权限" + privilege.getPrivilegeName());
                }
            }
        } finally {
    
    
            // 不要忘记关闭 sqlSession
            sqlSession.close();
        }
    }
}

运行测试,结果打印:

DEBUG [main] - ==>  Preparing: 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 = ? 
DEBUG [main] - ==> Parameters: 1(Long)
TRACE [main] - <==    Columns: id, user_name, user_password, user_email, user_info, head_img, create_time
TRACE [main] - <==        Row: 1, admin, 123456, admin_test@admin_test.email, <<BLOB>>, <<BLOB>>, 2020-01-01 01:11:12.0
DEBUG [main] - <==      Total: 1
用户名admin
DEBUG [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_time
TRACE [main] - <==        Row: 1, 管理员, 1, 1, 2020-01-01 17:02:14.0
TRACE [main] - <==        Row: 2, 普通用户, 1, 1, 2020-02-01 17:02:34.0
DEBUG [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 role_id = ? 
DEBUG [main] - ==> Parameters: 1(Long)
TRACE [main] - <==    Columns: id, privilege_name, privilege_url
TRACE [main] - <==        Row: 1, 用户管理, /users
TRACE [main] - <==        Row: 3, 系统日志, /logs
TRACE [main] - <==        Row: 2, 角色管理, /roles
DEBUG [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 role_id = ? 
DEBUG [main] - ==> Parameters: 2(Long)
TRACE [main] - <==    Columns: id, privilege_name, privilege_url
TRACE [main] - <==        Row: 4, 人员维护, /persons
TRACE [main] - <==        Row: 5, 单位维护, /companies
DEBUG [main] - <==      Total: 2
权限人员维护
权限单位维护

从日志可以看到,当执行 selectAllUserAndRolesSelect 方法后,可以得到 admin用户的信息,由于延迟加载,此时还不知道该用户有几个角色。当调用 user getRoleList()方法进行遍历时 MyBati 执行了第一层的嵌套查询,查询出了该用户的两个角色。对这两个角色进行遍历获取角色对应的权限信息,因为己经有两个角色,所以分别对两个角色进行遍历时会查询两次角色的权限信息。特别需要注意的是, 之所以可以根据需要查询数据,除了和fetchType 有关,还和全局的 aggressiveLazyLoading 属性有关,这个属性在介绍association 时被配置成了 false ,所以才会起到按需加载的作用。
mybatis-config.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="logImpl" value="LOG4J"/>
        <!-- 将以下画线方式命名的数据库列映射到-->
        <setting name="mapUnderscoreToCamelCase" value="true" />
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

    <typeAliases>
        <package name="cn.linst.model"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC">
                <property name="" value=""/>
            </transactionManager>
            <dataSource type="UNPOOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/learnmybatis?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>


    <databaseIdProvider type="DB_VENDOR">
        <property name="SQL Server" value="sqlserver" />
        <property name="DB2" value="db2" />
        <property name="Oracle" value="oracle" />
        <property name="MySQL" value="mysql"/>
        <property name="PostgreSQL" value="postgresql" />
        <property name="Derby" value="derby" />
        <property name="HSQL" value="hsqldb" />
        <property name="H2" value="h2" />
    </databaseIdProvider>

    <mappers>
        <mapper resource="cn/linst/mapper/CountryMapper.xml"/>
        <mapper resource="cn/linst/mapper/PrivilegeMapper.xml"/>
        <mapper resource="cn/linst/mapper/RoleMapper.xml"/>
        <mapper resource="cn/linst/mapper/RolePrivilegeMapper.xml"/>
        <mapper resource="cn/linst/mapper/UserMapper.xml"/>
        <mapper resource="cn/linst/mapper/UserRoleMapper.xml"/>
        <mapper resource="cn/linst/mapper1/CountryMapper.xml"/>
        <!--因为所有的 XML 映射文件都有对应的 Mapper 接口,所以还有一种更简单的配置方式-->
        <!--<package name="cn.linst.mapper"/>-->
    </mappers>

</configuration>

二、鉴别器映射
有时一个单独的数据库查询会返回很多不同数据类型(希望有些关联)的结果集。discriminator 鉴别器标签就是用来处理这种情况的 。
discriminator有以下属性:

属性 描述
column 用于设置要进行鉴别比较值的列
javaType 用于指定列的类型,保证使用相同的 Java 类型来比较值。discriminator 标签可以有1个或多个 case 标签, case 标签包含以下 3个属性。
value 该值为 discriminator 指定 column 用来匹配的值
resultMap 当 column 的值和 value 的值匹配时,可以配置使用 resultMap的映射, resultMap 优先级高于 resultType
resultType 当 column 的值和 value 的值匹配时,用于配置使用 resultType 指定的映射
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.linst.mapper.RoleMapper">

	<resultMap id="rolePrivilegeListMapChoose" type="cn.linst.model.SysRole">
        <discriminator column="enabled" javaType="int">
            <case value="1" resultMap="rolePrivilegeListMapSelect" />
            <case value="0" resultMap="roleMap"/>
        </discriminator>
    </resultMap>

    <resultMap id="rolePrivilegeListMapSelect" extends="roleMap" type="cn.linst.model.SysRole" >
        <collection property="privilegeList" fetchType="lazy" column="{roleId=id}" select="cn.linst.mapper.PrivilegeMapper.selectPrivilegeByRoleId"/>
    </resultMap>
    
   <resultMap id="roleMap" type="cn.linst.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>
    
    <select id="selectRoleByUserIdChoose" resultMap="rolePrivilegeListMapChoose" >
        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>
    
</mapper>

角色的属性 enable 值为1 的时候表示状态可用,为0 的时候表示状态不可用。当角色可用时, 使用 rolePrivilegeListMapSelect 映射,这是一对多的嵌套查询映射。当角色被禁用时,只能获取角色的基本信息,不能获得角色的权限信息。

RoleMapper:

package cn.linst.mapper;

import cn.linst.model.SysRole;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface RoleMapper {
    
    


    /**
     * 根据用户 ID 获取用户的角色信息
     * @param userid
     * @return
     */
    List<SysRole> selectRoleByUserIdChoose(Long userid);
}

RoleMapperTest:

package cn.linst;


import cn.linst.mapper.RoleMapper;
import cn.linst.model.SysPrivilege;
import cn.linst.model.SysRole;
import org.apache.ibatis.session.SqlSession;
import org.junit.Assert;
import org.junit.Test;

import java.util.List;

public class RoleMapperTest extends BaseMapperTest{
    
    
    @Test
    public void testselectRoleByUserIdChoose() {
    
    
        // 获取sqlSession
        SqlSession sqlSession = getSqlSession();
        try {
    
    
           //获取 RoleMapper 接口
            RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class) ;
            //由于数据库数据 enable 都是1 ,所以给其中一个角色的 enable 赋值为0
           // SysRole role= roleMapper.selectById(2L) ;
           // role.setEnabled(0) ;
           // roleMapper.updateById(role);
            //获取用户1 的角色
            List<SysRole> roleList= roleMapper.selectRoleByUserIdChoose(1L);
            for(SysRole r : roleList) {
    
    
                System.out.println("角色名:" + r.getRoleName()) ;
                if(r.getId().equals(1L)) {
    
    
                    //第一个角色存在权限信息
                    Assert.assertNotNull(r.getPrivilegeList());
                } else if (r.getId().equals (2L)) {
    
    
                    //第二个角色的权限为 null
                  //  Assert.assertNull(r.getPrivilegeList());
                  //  continue;
                }
                for(SysPrivilege privilege : r.getPrivilegeList()) {
    
    
                    System.out.println("权限名" + privilege.getPrivilegeName ());
                }
            }
        } finally {
    
    
            // 不要忘记关闭 sqlSession
            sqlSession.close();
        }
    }
}

运行结果:

DEBUG [main] - ==>  Preparing: select id, role_name roleName, enabled, create_by createBy, create_time createTime from sys_role where id = ? 
DEBUG [main] - ==> Parameters: 2(Long)
TRACE [main] - <==    Columns: id, roleName, enabled, createBy, createTime
TRACE [main] - <==        Row: 2, 普通用户, 1, 1, 2020-02-01 17:02:34.0
DEBUG [main] - <==      Total: 1
DEBUG [main] - ==>  Preparing: update sys_role set role_name = ?, enabled = ?, create_by = ?, create_time = ? where id = ? 
DEBUG [main] - ==> Parameters: 普通用户(String), 0(Integer), 1(Long), 2020-02-01 17:02:34.0(Timestamp), 2(Long)
DEBUG [main] - <==    Updates: 1
DEBUG [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_time
TRACE [main] - <==        Row: 1, 管理员, 1, 1, 2020-01-01 17:02:14.0
TRACE [main] - <==        Row: 2, 普通用户, 0, 1, 2020-02-01 17:02:34.0
DEBUG [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 role_id = ? 
DEBUG [main] - ==> Parameters: 1(Long)
TRACE [main] - <==    Columns: id, privilege_name, privilege_url
TRACE [main] - <==        Row: 1, 用户管理, /users
TRACE [main] - <==        Row: 3, 系统日志, /logs
TRACE [main] - <==        Row: 2, 角色管理, /roles
DEBUG [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 role_id = ? 
DEBUG [main] - ==> Parameters: 2(Long)
TRACE [main] - <==    Columns: id, privilege_name, privilege_url
TRACE [main] - <==        Row: 4, 人员维护, /persons
TRACE [main] - <==        Row: 5, 单位维护, /companies
DEBUG [main] - <==      Total: 2
权限名人员维护
权限名单位维护

猜你喜欢

转载自blog.csdn.net/tongwudi5093/article/details/114707474