1. 程式人生 > >【筆記】Mybatis高階查詢(小結)--巢狀查詢及延遲載入

【筆記】Mybatis高階查詢(小結)--巢狀查詢及延遲載入

<association><collection>標籤一對一、一對多,多對多查詢時用到的屬性

  • property:對應實體類中的屬性名,必填項。
  • javaType:屬性對應的型別。
  • resultMap:可以直接使用現有的resultMap,不需要再配置。
  • columnPrefix:查詢列的字首,配置字首後,在子標籤配置<result>的column時可省略字首。

1、<association>一對一的對映的使用例子

  • 在SysUser類中加入一對一的屬性role
	/**
     * 假設一個使用者只有一個角色(使用自動對映處理一對一關係)
     */
    private SysRole role;

    public SysRole getRole() {
		return role;
	}

	public void setRole(SysRole role) {
		this.role = role;
	}
  • javaType的使用例子:
  <!-- 使用resultMap的association標籤配置一對一對映 -->
  <resultMap id="userRoleMap3" extends="userMap" type="ex.mybatis.rbac.model.SysUser">
    
    <!-- role相關屬性,字首都加上了r_ -->
    <association property="role" columnPrefix="r_" javaType="ex.mybatis.rbac.model.SysRole">
	    <result column="id" property="id" />
	    <result column="role_name" property="roleName" />
	    <result column="enabled" property="enabled" />
	    <result column="create_by" property="createBy" />
	    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
    </association>
  </resultMap>
  • resultMap的使用例子(推薦使用):
  <!-- 使用resultMap的association標籤配置一對一對映 -->
  <resultMap id="userRoleMap4" extends="userMap" type="ex.mybatis.rbac.model.SysUser">
    
    <!-- role相關屬性,直接通過resultMap屬性引用roleMap,需要加上名稱空間的字首,列字首都加上了r_ -->
    <association property="role" columnPrefix="r_" resultMap="ex.mybatis.rbac.mapper.SysRoleMapper.roleMap" />
  </resultMap>
  • 查詢的SQL(適用於一條SQL查詢出所有結果的場景)
  <!-- 使用resultMap的association標籤配置一對一對映 -->
  <select id="selectUserAndRoleById3" resultMap="userRoleMap4">
    select 
	    u.id, 
	    u.user_name, 
	    u.user_password, 
	    u.user_email, 
	    u.create_time, 
	    u.user_info, 
	    u.head_img,
	    r.id r_id, 
	    r.role_name r_role_name, 
	    r.enabled r_enabled, 
	    r.create_by r_create_by, 
	    r.create_time r_create_time
    from sys_user u 
    inner join sys_user_role ur on u.id = ur.user_id
    inner join sys_role r on ur.role_id = r.id
    where u.id = #{id}
  </select>

2、<collection>一對多、多對多的對映查詢使用例子

  • 在SysUser類中加入一對多的屬性roles
	/**
     * 使用者的角色集合(一個使用者可以有多個角色)
     */
    private List<SysRole> roles;

	public List<SysRole> getRoles() {
		return roles;
	}

	public void setRoles(List<SysRole> roles) {
		this.roles = roles;
	}
  • javaType的使用例子
  <!-- 使用resultMap的association標籤配置一對一對映 -->
  <resultMap id="userRolesMap" extends="userMap" type="ex.mybatis.rbac.model.SysUser">
    
    <!-- role相關屬性,字首都加上了r_ -->
    <collection property="role" columnPrefix="r_" javaType="ex.mybatis.rbac.model.SysRole">
	    <result column="id" property="id" />
	    <result column="role_name" property="roleName" />
	    <result column="enabled" property="enabled" />
	    <result column="create_by" property="createBy" />
	    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
    </collection>
  </resultMap>
  • resultMap的使用例子(推薦使用)
  <!-- 使用resultMap的<collection>標籤進行一對多查詢 -->
  <resultMap id="userRolesMap" extends="userMap" type="ex.mybatis.rbac.model.SysUser">
    
    <!-- 角色的集合 -->
    <collection property="roles" columnPrefix="r_" resultMap="ex.mybatis.rbac.mapper.SysRoleMapper.roleMap"/>
  </resultMap>
  • 查詢的SQL(適用於一條SQL查詢出所有結果的場景)
  <!-- 使用resultMap的<collection>標籤進行一對多查詢 -->
  <select id="selectUserAndRoles" resultMap="userRolesMap">
    select 
	    u.id, 
	    u.user_name, 
	    u.user_password, 
	    u.user_email, 
	    u.create_time, 
	    u.user_info, 
	    u.head_img,
	    r.id r_id, 
	    r.role_name r_role_name, 
	    r.enabled r_enabled, 
	    r.create_by r_create_by, 
	    r.create_time r_create_time
    from sys_user u 
    inner join sys_user_role ur on u.id = ur.user_id
    inner join sys_role r on ur.role_id = r.id
    <where>
    	<if test="id != null">
    		u.id = #{id}
    	</if>
    </where>
  </select>

<association><collection>標籤實現巢狀查詢,需要用到以下屬性:

  • select:另一個對映查詢的ID,Mybatis會額外執行這個查詢獲取巢狀物件的結果。

  • column:列名或別名,將主查詢中列的結果作為巢狀查詢的引數,配置方式如column={prop1=col1,prop2=col2},prop1和prop2作為巢狀查詢的引數。

  • fetchType:資料的載入方式,可選值為lazy和eager,分別為延遲載入和積極載入。

	<!--  延遲載入與全域性配置aggressiveLazyLoading有關,需要設為false-->
	<settings>
		<!-- 延遲載入配置,3.4.5版本預設為false,當為true時<association>標籤的fetchType="lazy"無效,要生效必須為false-->
		<setting name="aggressiveLazyLoading" value="false" />
	</settings>

1、<association>一對一巢狀查詢及延遲載入使用例子

  • 角色子查詢方法selectRoleById(根據角色編號查詢角色資訊)
  <resultMap id="roleMap" type="ex.mybatis.rbac.model.SysRole">
    <id column="id" jdbcType="BIGINT" property="id" />
    <result column="role_name" jdbcType="VARCHAR" property="roleName" />
    <result column="enabled" jdbcType="INTEGER" property="enabled" />
    <result column="create_by" jdbcType="BIGINT" property="createBy" />
    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
  </resultMap>
  
  <!-- 根據角色編號查詢角色資訊-->
  <select id="selectRoleById" resultMap="roleMap">
    select id, role_name, enabled, create_by, create_time
    from sys_role
    where id = #{id}
  </select>
  • 主查詢方法selectRoleById(根據角色編號查詢角色資訊)
  <!-- 使用resultMap的association標籤進行巢狀查詢 -->
  <resultMap id="userRoleMapSelect" extends="userMap" type="ex.mybatis.rbac.model.SysUser">
    
    <!-- 巢狀查詢role,column配置的是巢狀查詢SQL的引數,當有多個時用逗號隔開, fetchType="lazy"實現延遲載入 -->
    <association property="role" fetchType="lazy" column="{id=role_id}" 
    select="ex.mybatis.rbac.mapper.SysRoleMapper.selectRoleById"/>
  </resultMap>
  
  <!-- 使用resultMap的association標籤進行巢狀查詢 -->
  <select id="selectUserAndRoleByIdSel" resultMap="userRoleMapSelect">
    select 
	    u.id, 
	    u.user_name, 
	    u.user_password, 
	    u.user_email, 
	    u.create_time, 
	    u.user_info, 
	    u.head_img,
	    ur.role_id
    from sys_user u 
    inner join sys_user_role ur on u.id = ur.user_id
    where u.id = #{id}
  </select>

2、<collection>一對多巢狀查詢及延遲載入使用例子

  • 許可權子查詢方法selectPriByRoleId(根據角色編號查詢角色許可權)
  <resultMap id="privilegeMap" type="ex.mybatis.rbac.model.SysPrivilege">
    <id column="id" jdbcType="BIGINT" property="id" />
    <result column="privilege_name" jdbcType="VARCHAR" property="privilegeName" />
    <result column="privilege_url" jdbcType="VARCHAR" property="privilegeUrl" />
  </resultMap>
  
<!-- 根據角色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>
  • 角色子查詢方法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>
  • 使用者主查詢方法selectRolesById(根據使用者編號查詢使用者資訊)
  <!-- 使用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>