天天看點

淺析Mybatis的resultMap的用法以及關聯結果集映射

一、resultType

  resultType 可以把查詢結果封裝到 pojo 類型中,但必須 pojo 類的屬性名和查詢到的資料庫表的字段名一緻。也就是說一般資料庫字段名喜歡用下劃線類型:user_id、而實體類通常是用駝峰 userId。如果這樣子那麼就對不上了,怎麼辦呢?

  如果 sql 查詢到的字段與 pojo 的屬性名不一緻,則需要使用 resultMap 将字段名和屬性名對應起來,進行手動配置封裝,将結果映射到pojo中。

二、resultMap用法

  resultMap是Mybatis最強大的元素,它可以将查詢到的複雜資料(比如查詢到幾個表中資料)映射到一個結果集當中。

  resultMap包含的元素:

<!--column不做限制,可以為任意表的字段,而property須為type 定義的pojo屬性-->
<resultMap id="唯一的辨別" type="映射的pojo對象">
  <id column="表的主鍵字段,或者可以為查詢語句中的别名字段" 
  jdbcType="字段類型" 
  property="映射pojo對象的主鍵屬性" />
  <result column="表的一個字段(可以為任意表的一個字段)" 
  jdbcType="字段類型" 
  property="映射到pojo對象的一個屬性(須為type定義的pojo對象中的一個屬性)"/>
  <association property="pojo的一個對象屬性" javaType="pojo關聯的pojo對象">
    <id column="關聯pojo對象對應表的主鍵字段" jdbcType="字段類型" property="關聯pojo對象的主席屬性"/>
    <result  column="任意表的字段" jdbcType="字段類型" property="關聯pojo對象的屬性"/>
  </association>
  <!-- 集合中的property須為oftype定義的pojo對象的屬性-->
  <collection property="pojo的集合屬性" ofType="集合中的pojo對象">
    <id column="集合中pojo對象對應的表的主鍵字段" jdbcType="字段類型" property="集合中pojo對象的主鍵屬性" />
    <result column="可以為任意表的字段" jdbcType="字段類型" property="集合中的pojo對象的屬性" />  
  </collection>
</resultMap>      

  如果collection标簽是使用嵌套查詢,格式如下:

<collection column="傳遞給嵌套查詢語句的字段參數"
property="pojo對象中集合屬性" 
ofType="集合屬性中的pojo對象"
select="嵌套的查詢語句" > 
 </collection>      

  注意:<collection>标簽中的column:要傳遞給select查詢語句的參數,如果傳遞多個參數,格式為column= ” {參數名1=表字段1,參數名2=表字段2} ;

  resultMap 可以實作将查詢結果映射為複雜類型的 pojo,比如在查詢結果映射對象中包括pojo和list實作一對一查詢和一對多查詢。

淺析Mybatis的resultMap的用法以及關聯結果集映射

1、先在Mapper檔案中,配置基本的sql語句

<!-- 查詢所有的訂單資料 -->
    <!-- resultMap:填入配置的resultMap标簽的id值 -->
    <select id="queryOrderAll" resultMap="orderResultMap">
        SELECT id, user_id,
        number,
        createtime, note FROM `order`
    </select>      

2、配置resultMap标簽,映射不同的字段和屬性名

  此處的 id 就對應上面的 resultMap,此處的 type 就對應你設定的實體類的 pojo

   <!-- resultMap最終還是要将結果映射到pojo上,type就是指定映射到哪一個pojo -->
    <!-- id:設定ResultMap的id -->
    <resultMap type="order" id="orderResultMap">
        <!-- 定義主鍵 ,非常重要。如果是多個字段,則定義多個id -->
        <!-- property:主鍵在pojo中的屬性名 -->
        <!-- column:主鍵在資料庫中的列名 -->
        <id property="id" column="id" />

        <!-- 定義普通屬性 -->
        <result property="userId" column="user_id" />
        <result property="number" column="number" />
        <result property="createTime" column="createtime" />
        <result property="note" column="note" />
    </resultMap>      

  結果就可以封裝到 pojo 中

三、使用resultMap進行關聯查詢

1、一對一查詢

  一對一資料模型:訂單使用者

  一個訂單資訊隻會是一個人下的訂單,是以從查詢訂單資訊出發關聯查詢使用者資訊為一對一查詢。

  如果從使用者資訊出發查詢使用者下的訂單資訊則為一對多查詢,因為一個使用者可以下多個訂單。

淺析Mybatis的resultMap的用法以及關聯結果集映射

(1)改造pojo類

  在訂單類中添加User屬性,User屬性是一個引用類型,用于存儲關聯查詢的使用者資訊,因為關聯關系是一對一,是以隻需要添加單個屬性即可

淺析Mybatis的resultMap的用法以及關聯結果集映射

(2)配置Mapper.xml配置檔案

  OrderMapper.xml — 先使用id和result屬性,映射order類的結果集,然後在使用association映射關聯對象User的結果集

<resultMap type="order" id="orderUserResultMap">
    <id property="id" column="id" />
    <result property="userId" column="user_id" />
    <result property="number" column="number" />
    <result property="createTime" column="createtime" />
    <result property="note" column="note" />

    <!-- association :配置一對一屬性 -->
    <!-- property:order裡面的User屬性名 -->
        <!-- javaType:屬性類型 -->
    <association property="user" javaType="user">
        <!-- id:聲明主鍵,表示user_id是關聯查詢對象的唯一辨別-->
        <id property="id" column="user_id" />
        <result property="username" column="username" />
        <result property="address" column="address" />
    </association>

</resultMap>      
<!-- 一對一關聯,查詢訂單,訂單内部包含使用者屬性 -->
<select id="queryOrderUserResultMap" resultMap="orderUserResultMap">
    SELECT
    o.id,
    o.user_id,
    o.number,
    o.createtime,
    o.note,
    u.username,
    u.address
    FROM
    `order` o
    LEFT JOIN `user` u ON o.user_id = u.id
</select>      
@Test
public void testQueryOrderUserResultMap() {
    // mybatis和spring整合,整合之後,交給spring管理
    SqlSession sqlSession = this.sqlSessionFactory.openSession();
    // 建立Mapper接口的動态代理對象,整合之後,交給spring管理
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    // 使用userMapper執行根據條件查詢使用者,結果封裝到Order類中
    List<Order> list = userMapper.queryOrderUserResultMap();
    for (Order o : list) {
        System.out.println(o);
    }
    // mybatis和spring整合,整合之後,交給spring管理
    sqlSession.close();
}      
淺析Mybatis的resultMap的用法以及關聯結果集映射

2、一對多查詢

  查詢所有使用者資訊及相關訂單。

(1)修改pojo類,在pojo類添加訂單集合屬性

淺析Mybatis的resultMap的用法以及關聯結果集映射

(2)修改UserMapper.xml配置檔案

  先使用id和result配置映射User類的結果,然後使用一對多關系的collection标簽配置Order結果

<resultMap type="user" id="userOrderResultMap">
    <id property="id" column="id" />
    <result property="username" column="username" />
    <result property="birthday" column="birthday" />
    <result property="sex" column="sex" />
    <result property="address" column="address" />

    <!-- 配置一對多的關系
        property:填寫pojo類中集合類類屬性的名稱
        javaType:填寫集合類型的名稱 
    -->
    <collection property="orders" javaType="list" ofType="order">
        <!-- 配置主鍵,是關聯Order的唯一辨別 -->
        <id property="id" column="oid" />
        <result property="number" column="number" />
        <result property="createtime" column="createtime" />
        <result property="note" column="note" />
    </collection>
</resultMap>

<!-- 一對多關聯,查詢訂單同時查詢該使用者下的訂單 -->
<select id="queryUserOrder" resultMap="userOrderResultMap">
    SELECT
    u.id,
    u.username,
    u.birthday,
    u.sex,
    u.address,
    o.id oid,
    o.number,
    o.createtime,
    o.note
    FROM
    `user` u
    LEFT JOIN `order` o ON u.id = o.user_id
</select>      

四、執行個體介紹resultMap的用法

1、建立商品pojo對象

public class TShopSku  {

    private Long id;
    private String skuName;
    private Long categoryId;
  ......
}      

  對應的resultMap

<resultMap id="BaseResultMap" type="com.meikai.shop.entity.TShopSku">
    <id column="ID" jdbcType="BIGINT" property="id" />
    <result column="SKU_NAME" jdbcType="VARCHAR" property="skuName" />
    <result column="CATEGORY_ID" jdbcType="BIGINT" property="categoryId" />
</resultMap>       

2、商品pojo類添加屬性集合:

  一個商品會有一些屬性,現在需要将查詢出的商品屬性添加到商品對象中,首先需要在原商品pojo類的基礎上中添加屬性的集合:

  // 屬性集合
    private List<TShopAttribute> attributes;
   
    public List<TShopAttribute> getAttributes() {
        return attributes;
    }
     public void setAttributes(List<TShopAttribute> attributes) {
        this.attributes = attributes;
     }      

  将Collection标簽添加到resultMap中,這裡有兩種方式:

1、嵌套結果:對應的resultMap:

<resultMap id="BasePlusResultMap" type="com.meikai.shop.entity.TShopSku">
    <id column="ID" jdbcType="BIGINT" property="id" />
    <result column="SKU_NAME" jdbcType="VARCHAR" property="skuName" />
    <result column="CATEGORY_ID" jdbcType="BIGINT" property="categoryId" />
    <collection property="attributes" ofType="com.meikai.shop.entity.TShopAttribute" > 
        <id column="AttributeID" jdbcType="BIGINT" property="id" />
        <result column="attribute_NAME" jdbcType="VARCHAR" property="attributeName" />
    </collection>
</resultMap>

// 查詢語句
<select id="getById"  resultMap="basePlusResultMap">
    select s.ID,s.SKU_NAME,s.CATEGORY_ID,a.ID,a.ATTRIBUTE_NAME
    from t_shop_sku s,t_shop_attribute a 
    where s.ID =a.SKU_ID and s.ID = #{id,jdbcType =BIGINT};
</select>      

2、關聯的嵌套查詢(在collection中添加select屬性):

  商品結果集映射resultMap:

<resultMap id="BasePlusResultMap" type="com.meikai.shop.entity.TShopSku">
    <id column="ID" jdbcType="BIGINT" property="id" />
    <result column="SKU_NAME" jdbcType="VARCHAR" property="skuName" />
    <result column="CATEGORY_ID" jdbcType="BIGINT" property="categoryId" />
    <collection column="{skuId=ID}" property="attributes" ofType="com.meikai.shop.entity.TShopAttribute" select="getAttribute" > 
    </collection>
</resultMap>      
<select id="getAttribute"  resultMap="AttributeResultMap">
    select a.ID,s.ATTRIBUTE_NAME
    from t_shop_attribute a
    where  a.ID = #{skuId,jdbcType =BIGINT};
</select>      
<resultMap id="AttributeResultMap" type="com.meikai.shop.entity.TShopAttribute">
    <id column="ID" jdbcType="BIGINT" property="id" />
    <result column="ATTRIBUTE_NAME" jdbcType="VARCHAR" property="attributeName" />
</resultMap>      
<select id="getById"  resultMap="BasePlusResultMap">
    select s.ID,s.SKU_NAME,s.CATEGORY_ID
    from t_shop_sku s
    where  s.ID = #{id,jdbcType =BIGINT};
</select>