1. 程式人生 > >MyBatis框架的學習(五)——一對一關聯對映和一對多關聯對映

MyBatis框架的學習(五)——一對一關聯對映和一對多關聯對映

在實際開發中我們不可能只是對單表進行操作,必然要操作多表,本文就來講解多表操作中的一對一關聯對映和一對多(或多對一)關聯對映,至於多對多關聯對映實質上也是兩個一對多(或多對一)關聯對映,所以在這裡我並不打算講解。先從一對一關聯對映講起。本文案例程式碼的編寫是建立在前文MyBatis框架的學習(四)——Mapper.xml檔案中的輸入和輸出對映以及動態sql案例基礎之上的!

一對一關聯對映

我以商品訂單資料模型為例來講解一對一關聯對映,如下:
這裡寫圖片描述

一對一查詢

有這樣一個需求:查詢所有訂單資訊,關聯查詢下單使用者資訊。
注意:因為一個訂單資訊只會是一個人下的訂單,所以從查詢訂單資訊出發關聯查詢使用者資訊為一對一查詢(值得注意的一點是這兒我將訂單與使用者的關係理解為一對多的關係,但實質上從訂單角度出發,多個訂單可屬於一個使用者,故訂單與使用者的關係應該是多對一的關係)。如果從使用者資訊出發查詢使用者下的訂單資訊則為一對多查詢,因為一個使用者可以下多個訂單。
解決該需求,可有兩種方法,先講第一種方法。

方法一

使用resultType,定義訂單資訊po類,此po類中包括了訂單資訊和使用者資訊。在cn.itheima.mybatis.po包下新建一個OrderUser類:

public class OrderUser extends Orders {

    private String username;
    private String address;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this
.username = username; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }

OrderUser類繼承Orders類後,OrderUser類包括了Orders類的所有欄位,只需要定義使用者的資訊欄位即可。
接著按照需求編寫sql語句,在OrderMapper.xml對映檔案中新增如下select元素:

<select id="getOrderUserList"
resultType="orderuser"> SELECT o.id, o.user_id userId, o.number, o.createtime, o.note, u.username, u.address FROM orders o LEFT JOIN `user` u ON o.user_id = u.id </select>

緊接著在OrderMapper介面中編寫如下方法:

List<OrderUser> getOrderUserList();

最後在OrderMapperTest單元測試類中編寫如下測試方法:

@Test
public void testGetOrderUserList() {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
    List<OrderUser> orderList = orderMapper.getOrderUserList();
    for (OrderUser orderUser : orderList) {
        System.out.println(orderUser);
    }
    sqlSession.close();
}

在testGetOrderUserList方法中的以下程式碼處打一個斷點:

for (OrderUser orderUser : orderList) {

然後以Debug模式執行該方法,大概就能看到你想要的結果了。
小結:定義專門的po類作為輸出型別,其中定義了sql查詢結果集所有的欄位。此方法較為簡單,企業中使用普遍

方法二

使用resultMap,定義專門的resultMap用於對映一對一查詢結果。首先在Orders類中加入user屬性,user屬性中用於儲存關聯查詢的使用者資訊,因為訂單關聯查詢使用者是一對一關係,所以這裡使用單個User物件儲存關聯查詢的使用者資訊。這樣Orders類的程式碼為:

public class Orders {
    private Integer id;

    private Integer userId;

    private String number;

    private Date createtime;

    private String note;

    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number == null ? null : number.trim();
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note == null ? null : note.trim();
    }

}

然後在OrderMapper.xml對映檔案中新增如下select元素:

<select id="getOrderUserResultMap" resultMap="order_user_resultmap">
    SELECT
        o.id,
        o.user_id,
        o.number,
        o.createtime,
        o.note,
        u.username,
        u.address
    FROM
        orders o
    LEFT JOIN `user` u ON o.user_id = u.id
</select>

上面id為order_user_resultmap的resultMap也須定義,如下:

<resultMap type="orders" id="order_user_resultmap">
    <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="user" javaType="cn.itheima.mybatis.po.User">
        <id property="id" column="user_id"/>
        <result property="username" column="username"/>
        <result property="address" column="address"/>
    </association>
</resultMap>

這裡resultMap指定order_user_resultmap。

  • association:表示進行關聯查詢單條記錄。
  • property:表示關聯查詢的結果儲存在cn.itcast.mybatis.po.Orders的user屬性中。即property對應Orders類裡面一對一關聯對映的那個屬性,即user屬性。
  • javaType:表示關聯查詢的結果型別。即user屬性的資料型別,可使用別名。
  • <id property="id" column="user_id"/>:查詢結果的user_id列對應關聯物件的id屬性,這裡是<id />表示user_id是關聯查詢物件的唯一標識。
  • <result property="username" column="username"/>:查詢結果的username列對應關聯物件的username屬性。

OrderMapper.xml對映檔案配置之後,在OrderMapper介面中編寫如下方法:

List<Orders> getOrderUserResultMap();

最後在OrderMapperTest單元測試類中編寫如下測試方法:

@Test
public void testGetOrderUserResultMap() {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
    List<Orders> orderList = orderMapper.getOrderUserResultMap();
    for (Orders orders : orderList) {
        System.out.println(orders);
    }
    sqlSession.close();
}

在testGetOrderUserResultMap方法中的以下程式碼處打一個斷點:

for (Orders orders : orderList) {

然後以Debug模式執行該方法,大概就能看到你想要的結果了。
小結:使用association完成關聯查詢,將關聯查詢資訊對映到pojo物件中

一對多關聯對映

現有這樣一個需求:查詢所有使用者資訊及使用者關聯的訂單資訊。這兒,使用者資訊和訂單資訊為一對多關係。在此,我使用resultMap來實現。
為了解決該需求,在User類中加入List<Orders> orders屬性,這樣User類的程式碼就為:

public class User {
    private Integer id; // int型別的id是不可能為null的!
    private String username;// 使用者姓名
    private String sex;// 性別
    private Date birthday;// 生日
    private String address;// 地址

    private List<Orders> orders;

    public List<Orders> getOrders() {
        return orders;
    }
    public void setOrders(List<Orders> orders) {
        this.orders = orders;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address="
                + address + "]";
    }
}

然後在OrderMapper.xml對映檔案中新增如下select元素:

<select id="getUserWithOrders" resultMap="user_order_resultmap">
    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 orders o ON u.id = o.user_id
</select>

上面id為user_order_resultmap的resultMap也須定義,如下:

<!-- 一對多關聯對映 -->
<resultMap type="user" id="user_order_resultmap">
    <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"/>
    <!-- 配置一對多關聯對映 -->
    <collection property="orders" ofType="orders">
        <!-- id對應Orders類的主鍵屬性 -->
        <id property="id" column="oid"/>
        <result property="number" column="number"/>
        <result property="createtime" column="createtime"/>
        <result property="note" column="note"/>
    </collection>
</resultMap>

這裡resultMap指定user_order_resultmap。

  • collection部分定義了使用者關聯的訂單資訊。表示關聯查詢結果集。
  • property=”orders”:關聯查詢的結果集儲存在User物件的哪個屬性上。即property對應User物件中的集合屬性。
  • ofType=”orders”:指定關聯查詢的結果集中的物件型別即List中的物件型別。此處可以使用別名,也可以使用全限定名。
  • <id /><result/>的意義同一對一查詢。

OrderMapper.xml對映檔案配置之後,在OrderMapper介面中編寫如下方法:

List<User> getUserWithOrders();

最後在OrderMapperTest單元測試類中編寫如下測試方法:

@Test
public void testGetUserWithOrders() {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
    List<User> userList = orderMapper.getUserWithOrders();
    for (User user : userList) {
        System.out.println(user);
    }
    sqlSession.close();
}

在testGetUserWithOrders方法中的以下程式碼處打一個斷點:

for (User user : userList) {

然後以Debug模式執行該方法,大概就能看到你想要的結果了。
至此,一對一關聯對映和一對多關聯對映我就已總結完了,覺得總結得蠻走心的。讀者如需檢視原始碼,可參考!