1. 程式人生 > >【筆記】Mybatis高階查詢(五)--使用resultMap的<collection>進行巢狀查詢及延遲載入

【筆記】Mybatis高階查詢(五)--使用resultMap的<collection>進行巢狀查詢及延遲載入

下面例子通過<collection>實現一個通過使用者編號查詢使用者下面的角色及許可權的需求,支援延遲載入。下面以自下而上的過程來實現這樣的巢狀查詢功能。並且這個自下而上的過程中每一個方法都是獨立可用的方法。上層的結果都以下層方法為基礎。所有物件都設定為延遲載入。

  1. 在最底層許可權表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>
    
  2. 在SysPrivilegeMapper介面中新增selectPriByRoleId方法
    	/**
         * 根據角色id查詢許可權
         * @param roleId
         * @return
         */
        List<SysPrivilege> selectPriByRoleId(Long roleId);
    
  3. 先測試一下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();
    		}
    	}
    
  4. 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]
    
  5. 到了中間層sys_role角色表了。在SysRole類中增加許可權屬性privileges
    	private List<SysPrivilege> privileges;
    
    	public List<SysPrivilege> getPrivileges() {
    		return privileges;
    	}
    
    	public void setPrivileges(List<SysPrivilege> privileges) {
    		this.privileges = privileges;
    	}
    
  6. 在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>
    
  7. 在SysRoleMapper介面中增加selectRolesById方法
    	/**
         * 使用resultMap的<collection>標籤進行一對多查詢,根據使用者編號查角色
         * @param id
         * @return
         */
        List<SysRole> selectRolesById(Long userId);
    
  8. 在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();
    		}
    	}
    
  9. 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]
    
  10. 最後到了項層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>
    
  11. 在SysUserMapper介面中增加selectUserById方法
    	/**
         * 使用resultMap的<collection>標籤進行一對多查詢,根據編號查使用者資訊
         * @param id
         * @return
         */
        SysUser selectUserById(Long id);
    
  12. 在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();
    		}
    	}
    
  13. 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]
    
  14. 到此需求功能已實現,首先通過使用者ID:1001查詢使用者資訊,然後呼叫user.getRoles()觸發selectRolesById查詢獲取使用者1001的角色,再通過呼叫role.getPrivileges()將查出來的角色ID傳給selectPriByRoleId查詢角色的許可權資訊。引數的傳遞:id->userId->roleId