一、一对多映射:
表结构参考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
权限名人员维护
权限名单位维护