天天看點

mybatis的association以及collection的用法前言:一、association的三種用法:二、collection的三種用法:總結:

前言:

在項目中,某些實體類之間肯定有關鍵關系,比如一對一,一對多等。在hibernate 中用

one to one

one to many

,而mybatis 中就用

association

collection

association: 一對一關聯(has one)

collection:一對多關聯(has many)

注意,隻有在做select查詢時才會用到這兩個标簽,都有三種用法,且用法類似。

一、association的三種用法:

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

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方法。

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

這種方法需要再定義CardDao.java,如下:

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

在CardDao.xml中實作該方法:

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

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

<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方法并且實作再引用才有用,不過這種方法思路清晰,易于了解。

2、第二種方法,嵌套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"引用。這種方法相比于第一種方法較為簡單。

3、第三種方法:嵌套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不能複用。具體用哪種方法,視情況而定。

二、collection的三種用法:

一個土豪有多個手機,看如下代碼:

User實體類

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如何定義:

1、第一種方法:用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。

2、第二種方法:嵌套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 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>
           

總結:

1、association表示的是has one的關系,一對一時使用。user has one card,是以在user的resultMap中接收card時應該用association;

2、collection表示的是has many的關系,一對多時使用。user has many mobilePhone,是以在user的resultMap中接收mobilePhone時應該用collection 。

3、都有三種用法,且非常類似,resultMap要複用建議第二種方法,不需要複用建議第三種方法。

4、特别注意表中主鍵字段要有所區分,不能都寫成id,要寫成user_id、card_id,反正要有所區分,不然查詢的時候會查不到完整的資料。

以上屬于個人筆記整理,如果錯誤,歡迎批評指正!