下面例子通过
<collection>
实现一个通过用户编号查询用户下面的角色及权限的需求,支持延迟加载。下面以自下而上的过程来实现这样的嵌套查询功能。并且这个自下而上的过程中每一个方法都是独立可用的方法。上层的结果都以下层方法为基础。所有对象都设置为延迟加载。
- 在最底层权限表sys_privilege的映射文件SysPrivilegeMapper.xml中添加selectPriByRoleId方法,实现通过角色编号查询对应权限
<!-- 根据角色id查询权限 --> <select id="selectPriByRoleId" resultMap="privilegeMap"> select id, privilege_name, privilege_url from sys_privilege p inner join sys_role_privilege rp on rp.privilege_id = p.id where rp.role_id = #{roleId} </select>
- 在SysPrivilegeMapper接口中添加selectPriByRoleId方法
/** * 根据角色id查询权限 * @param roleId * @return */ List<SysPrivilege> selectPriByRoleId(Long roleId);
- 先测试一下selectPriByRoleId方法,在PrivilegeMaperTest中增加selectPriByRoleId对应测试方法
@Test public void testSelectPriByRoleId() { // 获取SqlSession SqlSession sqlSession = openSession(); try { // 获取PrivilegeMapper接口 SysPrivilegeMapper privilegeMapper = sqlSession.getMapper(SysPrivilegeMapper.class); // 调用selectPriByRoleId方法 List<SysPrivilege> privileges = privilegeMapper.selectPriByRoleId(1L); // user不为空 Assert.assertNotNull(privileges); System.out.println(); for (SysPrivilege privilege : privileges) { System.out.println(privilege); } } finally { sqlSession.close(); } }
- selectPriByRoleId方法的测试结果,通过结果查看selectPriByRoleId方法可以单独使用
[ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - ==> Preparing: select id, privilege_name, privilege_url from sys_privilege p inner join sys_role_privilege rp on rp.privilege_id = p.id where rp.role_id = ? [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - ==> Parameters: 1(Long) [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - <== Columns: id, privilege_name, privilege_url [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - <== Row: 1, 用户管理, /users [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - <== Row: 2, 角色管理, /roles [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - <== Row: 3, 系统日志, /logs [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - <== Total: 3 SysPrivilege [id=1, privilegeName=用户管理, privilegeUrl=/users] SysPrivilege [id=2, privilegeName=角色管理, privilegeUrl=/roles] SysPrivilege [id=3, privilegeName=系统日志, privilegeUrl=/logs]
- 到了中间层sys_role角色表了。在SysRole类中增加权限属性privileges
private List<SysPrivilege> privileges; public List<SysPrivilege> getPrivileges() { return privileges; } public void setPrivileges(List<SysPrivilege> privileges) { this.privileges = privileges; }
- 在SysRoleMapper.xml中配置映射rolePrisMapSel和对应的查询方法selectRolesById
<!-- 使用resultMap的<collection>标签进行一对多查询,根据用户查询角色信息 --> <resultMap id="rolePrisMapSel" extends="roleMap" type="ex.mybatis.rbac.model.SysRole"> <!-- 角色权限的集合 --> <collection property="privileges" fetchType="lazy" column="{roleId=id}" select="ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId" /> </resultMap> <!-- 使用resultMap的<collection>标签进行一对多查询,查询角色对应的权限 --> <select id="selectRolesById" resultMap="rolePrisMapSel"> 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>
- 在SysRoleMapper接口中增加selectRolesById方法
/** * 使用resultMap的<collection>标签进行一对多查询,根据用户编号查角色 * @param id * @return */ List<SysRole> selectRolesById(Long userId);
- 在RoleMaperTest中增加selectRolesById对应的测试方法
@Test public void testSelectRolesById() { // 获取SqlSession SqlSession sqlSession = openSession(); try { // 获取SysRoleMapper接口 SysRoleMapper roleMapper = sqlSession.getMapper(SysRoleMapper.class); // 调用selectRolesById方法 List<SysRole> roles = roleMapper.selectRolesById(1L); System.out.println("角色数:" + roles.size()); for (SysRole role : roles) { System.out.println("调用role.getPrivileges()获取权限"); System.out.println("\n角色:" + role); for (SysPrivilege privilege : role.getPrivileges()) { System.out.println("--权限:" + privilege); } System.out.println(); } System.out.println(); } finally { sqlSession.close(); } }
- selectRolesById测试结果,可以看到用户1001有一个角色2,然后角色2有2个权限。在调用了role.getPrivileges()的时候才用roleId=2去查询权限信息。因为使用了延时加载。
[ex.mybatis.rbac.mapper.SysRoleMapper.selectRolesById] - ==> 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 = ? [ex.mybatis.rbac.mapper.SysRoleMapper.selectRolesById] - ==> Parameters: 1001(Long) [ex.mybatis.rbac.mapper.SysRoleMapper.selectRolesById] - <== Columns: id, role_name, enabled, create_by, create_time [ex.mybatis.rbac.mapper.SysRoleMapper.selectRolesById] - <== Row: 2, 普通用户, 0, 1, 2018-10-01 18:27:37.0 [ex.mybatis.rbac.mapper.SysRoleMapper.selectRolesById] - <== Total: 1 角色数:1 调用role.getPrivileges() [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - ==> Preparing: select id, privilege_name, privilege_url from sys_privilege p inner join sys_role_privilege rp on rp.privilege_id = p.id where rp.role_id = ? [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - ==> Parameters: 2(Long) [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - <== Columns: id, privilege_name, privilege_url [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - <== Row: 4, 人员维护, /persons [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - <== Row: 5, 单位维护, /companies [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - <== Total: 2 角色:SysRole [id=2, roleName=普通用户, enabled=disabled, createBy=1, createTime=Mon Oct 01 18:27:37 CST 2018] --权限:SysPrivilege [id=4, privilegeName=人员维护, privilegeUrl=/persons] --权限:SysPrivilege [id=5, privilegeName=单位维护, privilegeUrl=/companies]
- 最后到了项层sys_user了,通过用户id查询用户信息,在SysUserMapper.xml中增加配置映射userRolesMapSel和对应的查询方法selectUserById
<!-- 使用resultMap的<collection>标签进行一对多查询 ,根据编号查用户信息--> <resultMap id="userRolesMapSel" extends="userMap" type="ex.mybatis.rbac.model.SysUser"> <!-- 角色的集合 --> <collection property="roles" fetchType="lazy" column="{userId=id}" select="ex.mybatis.rbac.mapper.SysRoleMapper.selectRolesById"/> </resultMap> <!-- 使用resultMap的<collection>标签进行一对多查询,根据编号查用户信息 --> <select id="selectUserById" resultMap="userRolesMapSel"> select id, user_name, user_password, user_email, create_time, user_info, head_img from sys_user where id = #{id} </select>
- 在SysUserMapper接口中增加selectUserById方法
/** * 使用resultMap的<collection>标签进行一对多查询,根据编号查用户信息 * @param id * @return */ SysUser selectUserById(Long id);
- 在UserMaperTest中增加selectUserById对应的测试方法
@Test public void testSelectUserById() { // 获取SqlSession SqlSession sqlSession = openSession(); try { // 获取SysUserMapper接口 SysUserMapper userMapper = sqlSession.getMapper(SysUserMapper.class); // 调用selectUserById方法 SysUser user = userMapper.selectUserById(1L); // user不为空 Assert.assertNotNull(user); // 查询用户下有多少角色 System.out.println("\n调用user.getRoles()获取角色"); List<SysRole> roles = user.getRoles(); System.out.println("角色数:" + roles.size()); for (SysRole role : roles) { System.out.println("\n调用role.getPrivileges()获取权限"); for (SysPrivilege privilege : role.getPrivileges()) { System.out.println("--权限:" + privilege); } } } finally { sqlSession.close(); } }
- selectUserById测试结果
[ex.mybatis.rbac.mapper.SysUserMapper.selectUserById] - ==> Preparing: select id, user_name, user_password, user_email, create_time, user_info, head_img from sys_user where id = ? [ex.mybatis.rbac.mapper.SysUserMapper.selectUserById] - ==> Parameters: 1001(Long) [ex.mybatis.rbac.mapper.SysUserMapper.selectUserById] - <== Columns: id, user_name, user_password, user_email, create_time, user_info, head_img [ex.mybatis.rbac.mapper.SysUserMapper.selectUserById] - <== Row: 1001, test, 123456, [email protected], 2018-10-02 17:17:11.0, <<BLOB>>, <<BLOB>> [ex.mybatis.rbac.mapper.SysUserMapper.selectUserById] - <== Total: 1 调用user.getRoles()获取角色 [ex.mybatis.rbac.mapper.SysRoleMapper.selectRolesById] - ==> 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 = ? [ex.mybatis.rbac.mapper.SysRoleMapper.selectRolesById] - ==> Parameters: 1001(Long) [ex.mybatis.rbac.mapper.SysRoleMapper.selectRolesById] - <== Columns: id, role_name, enabled, create_by, create_time [ex.mybatis.rbac.mapper.SysRoleMapper.selectRolesById] - <== Row: 2, 普通用户, 0, 1, 2018-10-01 18:27:37.0 [ex.mybatis.rbac.mapper.SysRoleMapper.selectRolesById] - <== Total: 1 角色数:1 调用role.getPrivileges()获取权限 [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - ==> Preparing: select id, privilege_name, privilege_url from sys_privilege p inner join sys_role_privilege rp on rp.privilege_id = p.id where rp.role_id = ? [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - ==> Parameters: 2(Long) [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - <== Columns: id, privilege_name, privilege_url [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - <== Row: 4, 人员维护, /persons [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - <== Row: 5, 单位维护, /companies [ex.mybatis.rbac.mapper.SysPrivilegeMapper.selectPriByRoleId] - <== Total: 2 角色:SysRole [id=2, roleName=普通用户, enabled=disabled, createBy=1, createTime=Mon Oct 01 18:27:37 CST 2018] --权限:SysPrivilege [id=4, privilegeName=人员维护, privilegeUrl=/persons] --权限:SysPrivilege [id=5, privilegeName=单位维护, privilegeUrl=/companies]
- 到此需求功能已实现,首先通过用户ID:1001查询用户信息,然后调用user.getRoles()触发selectRolesById查询获取用户1001的角色,再通过调用role.getPrivileges()将查出来的角色ID传给selectPriByRoleId查询角色的权限信息。参数的传递:id->userId->roleId