Mybatis-高級映射

  1. 一對一映射:

    • 使用自動映射處理一對一關係:

      public class User {
          private Integer id;
          private String username;
          private String userEmail;
          /**
           * 角色
           */
          private Role role;
          
          // 省略其它代碼
      }
      
      public class Role {
          private Integer id;
          private String roleName;
          // 省略其它代碼
      }
      
      <select id="selectUserAndRoleById" resultType="study.User">
          SELECT 
                 id,
                 username,
                 userEmail,
                 <!--注意這裏的別名-->
                 role.id AS "role.id",
                 <!--注意這裏的別名-->
                 role.role_name AS "role.roleName"
            FROM user 
                 INNER JOIN user_role 
                         ON user_role.role_id = user.id
                 INNER JOIN role
                         ON role.id = user_role.role_id
            WHERE user.id = #{id}
      </select>
      
    • 使用 resultMap 配置一對一映射:

      • 一般寫法:

        <resultMap id="uesrRoleMap" type="study.User">
            <id property="id" column="id"/>
            <result property="username" column="username"/>
            <result property="userEmail" column="user_email"/>
            <result property="role.id" column="role_id"/>
            <result property="role.roleName" column="role_name"/>
        </resultMap>
        
        <select id="selectUserAndRoleById" resultMap="uesrRoleMap">
            SELECT 
                   id,
                   username,
                   userEmail,
                   <!--注意這裏的別名-->
                   role.id AS role_id,
                   <!--注意這裏的別名-->
                   role.role_name
              FROM user 
                   INNER JOIN user_role 
                           ON user_role.role_id = user.id
                   INNER JOIN role
                           ON role.id = user_role.role_id
              WHERE user.id = #{id}
        </select>
        

        注意這裏在 resultMap 中配置的 column 名稱要和 SQL 語句查詢結果的別名相同.

      • 使用繼承的方式:

        <!--User 的 resultMap-->
        <resultMap id="userMap" type="study.User">
            <!--這些是可以被繼承的-->
            <id property="id" column="id"/>
            <result property="username" column="username"/>
            <result property="userEmail" column="user_email"/>
        </resultMap>
        
        <!--帶 Role 的 User 的 resultMap-->
        <resultMap id="uesrRoleMap" extends="userMap" type="study.User">
            <result property="role.id" column="role_id"/>
            <result property="role.roleName" column="role_name"/>
        </resultMap>
        

        這裏繼承的只是 userMap 中的 id 和 result 子元素.

      • 使用 Association 方式:

        <resultMap id="uesrRoleMap" extends="userMap" type="study.User">
            <association property="role" columnPrefix="role_" javaType="study.Role">
                <result property="id" column="id"/>
                <result property="roleName" column="role_name"/>
            </association>
        </resultMap>
        
        <select id="selectUserAndRoleById" resultMap="uesrRoleMap">
            SELECT 
                   id,
                   username,
                   userEmail,
                   <!--注意這裏的別名, 所有列名必須要有 role_ 前綴-->
                   role.id AS role_id,
                   <!--注意這裏的別名, 所有列名必須要有 role_ 前綴-->
                   role.role_name AS role_role_name
              FROM user 
                   INNER JOIN user_role 
                           ON user_role.role_id = user.id
                   INNER JOIN role
                           ON role.id = user_role.role_id
              WHERE user.id = #{id}
        </select>
        
    • association 標籤的嵌套查詢:

      <resultMap id="uesrRoleMap" extends="userMap" type="study.User">
          <association property="role" javaType="study.Role" column="{id=role_ID}"
          select="study.mapper.RoleMapper.selectRoleById"/>
      </resultMap>
      
      <select id="selectUserAndRoleByIdSelect" resultMap="uesrRoleMap">
          SELECT 
                 id,
                 username,
                 userEmail,
                 user_role.role_id
            <!--注意這裏並沒有從 role 表中查詢信息了-->
            FROM user 
                 INNER JOIN user_role 
                         ON user_role.role_id = user.id
            WHERE user.id = #{id}
      </select>
      
      <select id="selectRoleById" resultMap="roleMap">
          SELECT id,
                 role_name
            FROM role
           WHERE id = #{id} 
      </select>
      

      這裏還可以將 fetchType 設置爲 lazy. 這樣設置之後, 只有當調用 User#getRole() 方法纔會執行嵌套查詢去獲取數據. 這時需要將在
      mybatis-config.xml 中增加:

      <settings>
          <setting name="aggressiveLazyLoading" value="false"/>
      </settings>
      

      Mybatis 還提供了 lazyLoadTriggerMethods 來定義某些方法, 當調用這些方法時, 會加載全部的延遲加載數據.

  2. 一對多映射:

    • collection 集合的嵌套結果映射:

      public class User {
          private Integer id;
          private String username;
          private String userEmail;
          /**
           * 角色
           */
          private List<Role> roles;
          
          // 省略其它代碼
      }
      
      <resultMap id="uesrRoleMap" extends="userMap" type="study.User">
          <collection property="roles" columnPrefix="role_" javaType="study.Role"
          <!--這裏引用 roleMap -->
          resultMap="study.mapper.RoleMapper.roleMap"/>
      </resultMap>
      
      <select id="selectAllUserAndRoles" resultMap="uesrRoleMap">
          SELECT 
                 id,
                 username,
                 userEmail,
                 <!--注意這裏的別名, 所有列名必須要有 role_ 前綴-->
                 role.id AS role_id,
                 <!--注意這裏的別名, 所有列名必須要有 role_ 前綴-->
                 role.role_name AS role_role_name
            FROM user 
                 INNER JOIN user_role 
                         ON user_role.role_id = user.id
                 INNER JOIN role
                         ON role.id = user_role.role_id
      </select>
      

      Mybatis 在處理結果的時候, 會判斷結果是否相同. 如果是相同的結果, 則只會保留第一個結果. MyBatis 判斷結果是否相同時, 最簡單的是根據 resultMap 中映射配置的 id 標籤. 在 userMap 中配置如下:

      <id property="id" column="id"/>
      

      id 的唯一作用就是在嵌套的映射配置時判斷數據相同.

  3. 鑑別器映射:

     ```
     <resultMap id="userRoleMapChoose" resultType="study.User">
         <discriminator column="enabled" javaType="int">
             <case value="1" resultMap="uesrRoleMap"/>
             <case value="0" resultMap="userMap"/>
         </discriminator>
     </resultMap>
     
     <select id="selectUserAndRoleById" resultMap="userRoleMapChoose">
         SELECT 
                id,
                username,
                userEmail,
                <!--注意這裏的別名-->
                role.id AS "role.id",
                <!--注意這裏的別名-->
                role.role_name AS "role.roleName"
           FROM user 
                INNER JOIN user_role 
                        ON user_role.role_id = user.id
                INNER JOIN role
                        ON role.id = user_role.role_id
           WHERE user.id = #{id}
     </select>
     ```
    

    當用戶的 enabled 值爲 1 的時候表示用戶被啓用, 0 的時候表示用戶不可用. 當用戶可用時, 使用 userRoleMap 映射, 可以獲取到用戶信息和角色信息; 當用戶不可以用時, 使用 userMap 只能獲取到用戶信息.

  4. 參考:
    [1] : MyBatis從入門到精通

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章