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条数据,就会合并为一条。

运行测试,打印结果:

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
权限名人员维护
权限名单位维护
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值