mybatis中:association和collection的區別

某些實體類之間確定有關鍵關係,好比一對一,一對多等。在hibernate 中用one to oneone to many,而mybatis 中就用associationcollection
association: 一對一關聯(has one)
collection:一對多關聯(has many)
注意,只有在作select查詢時纔會用到這兩個標籤,都有三種用法,且用法相似。java

1、association的三種用法:

先看以下代碼(省略set、get方法):sql

public class User {
    private Integer userId;
    private String userName;
    private Integer age;
    private Card card;//一我的一張身份證,1對1
}
public class Card {
    private Integer cardId;
    private String cardNum;//身份證號
    private String address;//地址
}
public interface UserDao {
    /**
     * 經過userId查詢user信息
     * @param userId
     * @return
     */
    User queryById(int userId);

}
<select id="queryById" parameterType="int" resultMap="userMap">
        SELECT u.user_name,u.age,c.card_id,c.card_num,c.address
        FROM tb_user u,tb_card c
        WHERE u.card_id=c.card_id
        AND
        u.user_id=#{userId}
    </select>

以上是實體類、dao層的設計以及在UserDao.xml中queryById方法的sql語句的編寫,由於不論用association的哪一種方式,sql語句都是同樣的寫,不一樣的只是userMap的寫法,因此這裏先給出這段代碼。User詢Card是一對一關係,在數據庫中,tb_user表經過外鍵card_id關聯tb_card表。下面分別用association的三種用法來實現queryById方法。數據庫

一、第一種用法:association中使用select

這種方法須要再定義CardDao.java,以下:mybatis

public interface CardDao {
    Card queryCardById(int cardId);
}

在CardDao.xml中實現該方法:spa

<select id="queryCardById" parameterType="int" resultType="Card">
        SELECT *
        FROM tb_card
        WHERE card_id=#{cardId}
 </select>

而後再看UserDao.xml中是如何引用這個方法的:hibernate

<resultMap type="User" id="userMap">
    <result property="userName" 
         column="user_name"/>
    <result property="age" 
         column="age"/>
   <association property="card" 
         column="card_id" 
         select="com.zhu.ssm.dao.
         CardDao.queryCardById">
   </association>
</resultMap>

在這裏直接經過select引用CardDao的queryById方法。我的感受這種方法比較麻煩,由於還要在CardDao裏定義queryCardById方法而且實現再引用纔有用,不過這種方法思路清晰,易於理解。設計

二、第二種方法,嵌套resultMap

<resultMap type="Card" id="cardMap">
      <id property="cardId" 
            column="card_id"/>
      <result property="cardNum" 
                   column="card_num"/>
      <result property="address" 
                   column="address"/>
</resultMap>


<resultMap type="User" id="userMap">
     <result property="userName" 
                  column="user_name"/>
     <result property="age" 
                  column="age"/>
     <association property="card" 
                             resultMap="cardMap">
     </association>
</resultMap>

第二種方法就是在UserDao.xml中先定義一個Card的resultMap,而後在User的resultMap的association標籤中經過resultMap="cardMap"引用。這種方法相比於第一種方法較爲簡單。code

三、第三種方法:嵌套resultMap簡化版

<resultMap type="User" id="userMap">
   <result property="userName" 
                  column="user_name"/>
   <result property="age" 
                  column="age"/>
   <association 
          property="card"
          column="card_id" 
          javaType="Card">
      <id property="cardId" 
                column="card_id"/>
      <result property="cardNum"
                       column="card_num"/>
      <result property="address" 
                       column="address"/>
    </association>
</resultMap>

這種方法就把Card的resultMap定義在了association 標籤裏面,經過javaType來指定是哪一個類的resultMap,我的認爲這種方法最簡單,缺點就是cardMap不能複用。具體用哪一種方法,視狀況而定。xml

2、collection的三種用法:

一個土豪有多個手機,看以下代碼:
User實體類ci

public class User{
  private Integer userId;
    private String userName;
    private Integer age;
    private List<MobilePhone> mobilePhone;//土豪,多個手機,1對多
}

手機類

public class MobilePhone {
    private Integer mobilePhoneId;
    private String brand;//品牌
    private double price;//價格
    private User user;//主人
}

dao層

public interface UserDao {
    /**
     * 經過userId查詢user信息
     * @param userId
     * @return
     */
    User queryById(int userId);
}

UserDao.xml中的select查詢語句

<select id="queryById" parameterType="int" resultMap="userMap">
        SELECT u.user_name,u.age,
                       m.brand,m.price
        FROM tb_user u,tb_mobile_phone m
        WHERE m.user_id=u.user_id
        AND
        u.user_id=#{userId}
</select>

數據庫中,tb_mobile_phone中user_id做爲外鍵。那麼下面來看resultMap如何定義:

一、第一種方法:用select,跟association 中使用select相似:

先定義 MobilePhoneDao.java

public interface MobilePhoneDao {
    List<MobilePhone> queryMbByUserId(int userId);
}

而後實現該方法 MobilePhoneDao.xml

<resultMap type="MobilePhone"
                    id="mobilePhoneMap">
     <id property="mobilePhoneId" 
           column="user_id"/>
     <result property="brand" 
                  column="brand"/>
     <result property="price" 
                  column="price"/>
     <association property="user" 
               column="user_id" select=
      "com.zhu.ssm.dao.UserDao.queryById">
     </association>
</resultMap>
<select id="queryMbByUserId" parameterType="int" resultMap="mobilePhoneMap">
        SELECT brand,price
        FROM tb_mobile_phone
        WHERE user_id=#{userId}
    </select>

作好以上準備工做,那就能夠在UserDao.xml中引用了

<resultMap type="User" id="userMap">
        <id property="userId" column="user_id"/>
        <result property="userName" 
                     column="user_name"/>
    <result property="age" 
                     column="age"/>
    <collection property="mobilePhone" 
                column="user_id" 
                select="com.zhu.ssm.dao
       .MobilePhoneDao.queryMbByUserId">
        </collection>
</resultMap>

這種方法和association的第一種用法幾乎是同樣的不一樣之處就是mobilePhMap中用到了association ,queryMbByUserId中要使用mobilePhoneMap,而不能直接使用resultType。

二、第二種方法:嵌套resultMap

<resultMap type="MobilePhone" id="mobilephoneMap">
         <id column="mobile_phone_id" property="mobilePhoneId"/>
         <result column="brand" property="brand" />
         <result column="price" property="price" /></resultMap>
<resultMap type="User" id="userMap">
        <result property="userName" column="user_name"/>
        <result property="age" column="age"/>
        <collection property="mobilePhone" resultMap="mobilephoneMap" >
        </collection>
</resultMap>

定義好這兩個resultMap,再引用UserMap就好了。

三、第三種方法:嵌套resultMap簡化版

<resultMap type="User" id="userMap">
        <result property="userName" column="user_name"/>
     <result property="age" column="age"/>
     <collection property="mobilePhone"
                  column="user_id" 
                 ofType="MobilePhone">
      <id column="mobile_phone_id" property="mobilePhoneId" />
      <result column="brand" 
                       property="brand" />
      <result column="price"
                      property="price" />
 </collection>
</resultMap>

這種方法須要注意,必定要有ofType,collection 裝的元素類型是啥ofType的值就是啥,這個必定不能少。
注意:
全部resultMap中的type、select 標籤中的resultType以及association中的javaType,collection中的ofType,這裏只寫了類名,是由於在mybatis-config.xml中配置了typeAliases,不然就要寫該類的全類名。配置以下:

<typeAliases>
<packagename="com.zhu.smm.entity"/>
</typeAliases>

總結:

一、association表示的是has one的關係,一對一時使用。user has one card,因此在user的resultMap中接收card時應該用association;
二、collection表示的是has many的關係,一對多時使用。user has many mobilePhone,因此在user的resultMap中接收mobilePhone時應該用collection 。
三、都有三種用法,且很是相似,resultMap要複用建議第二種方法,不須要複用建議第三種方法。
四、特別注意表中主鍵字段要有所區分,不能都寫成id,要寫成user_id、card_id,反正要有所區分,否則查詢的時候會查不到完整的數據。

相關文章
相關標籤/搜索