對于資料庫中對表的增删改查操作,我們知道增删改都涉及的是單表,而隻有查詢操作既可以設計到單表操作又可以涉及到多表操作,是以對于輸入映射parameterType而言是沒有所謂的進階映射的,也就是說進階映射隻針對于輸出映射(因為進階映射設計到多張表)。
前五篇文章我們都隻實作了單表中的字段與pojo的映射,而本篇文章我們将來講解如何實作多表與pojo之間的進階映射,分别有一對一映射、一對多映射和多對多映射。首先我們來看看如何使用resultType完成一對一映射。
1.多表間的一對一查詢
1.1需求
查詢訂單資訊關聯查詢使用者資訊。這裡我們知道一個使用者可以有多張訂單,而一張訂單隻能屬于一個使用者,是以使用者與訂單間的關系是一對多而訂單與使用者間的關系是一對一。是以這裡我們将訂單表作為主查詢表來關聯使用者表,進而實作一對一映射。
1.2建立表和資料
1
2
3
4
5
6
create table orders( id int primary key auto_increment,
user_id int ,
number int,
createtime datetime, note varchar(50));
使用者表在第一篇文章中我們已經建立。
建立oders表和user表對應的pojo對象Orders.java和User.java。
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Orders
{
private Integer id;
private Integer userId;
private String number;
private Date createtime;
private String note;
}
并建立相關的get和set方法,User.java我們之前已建立。
1.3sql查詢語句
對于查詢語句,我們需要知道:1.先确定主查詢表:訂單表。2.再确定關聯查詢表:使用者資訊表。通過orders關聯查詢使用者使用user_id一個外鍵,隻能關聯查詢出一條使用者記錄,我們使用内連接配接。查詢語句為:
1
2
3
SELECT orders.*,user.username,user.sex
FROM orders,user
WHERE orders.user_id = user.id
1.4使用resultType實作
通過查詢語句,查詢到的結果同時包括user表和orders表兩張表的列,那麼我們将結果映射到哪個pojo對象中呢?若映射到User.java,那查詢結果中對應的orders表的字段一定會遺失;若映射到Orders.java,那查詢結果中對應的user表的字段同樣也會遺失。是以這裡需要我們針對查詢的結果重新建立一個映射的pojo對象OrderCustom.java:
這裡我們讓OrderCustom.java繼承自Order.java,這樣我們就隻需在OrderCustom.java中添加user表中的字段即可。因為MyBatis主要的重點在sql語句,是以我們完成配置和pojo對象的建立後主要的點就放在了sql語句上,是以接下來要定義寫sql語句的mapper.xml和對資料庫進行操作的mapper.java接口了.
OrdersMapperCustom.xml檔案内容如下:
因為我們隻關心輸出映射,是以在xml中寫sql查詢語句時沒有寫parameterType屬性,而resultType的屬性值我之是以沒有寫全OrderCustom類的全限定性名,是因為我們在SqlMapperConfig.xml中進行了别名的配置。相應的OrdersMapperCustom.java接口内容如下:
然後在測試類中測試:
便可完成這兩張表的關聯與我們自定義的pojo對象的映射。接下來我們看看如何使用resultMap完成。
1.5使用resultMap實作一對一映射
思路:将關聯查詢的資訊映射到pojo中,如下:隻需在Orders類中建立一個User屬性,将關聯查詢的資訊映射到User屬性中。
這樣我們便可以将查詢的結果映射到Orders.java類中,而不用自己再自定義一個pojo了。
修改OrdersMapperCustom.xml中的内容(添加并使用resultMap标簽),:
然後在OrdersMapperCutom.java中添加方法:
最後測試:
發現查詢結果已全部映射到Orders.java類中。
1.6比較resultType和resultMap完成一對一映射
resultType:要自定義pojo 保證sql查詢列和pojo的屬性對應,這種方法相對較簡單,是以應用廣泛。
resultMap:使用association完成一對一映射需要配置一個resultMap标簽,過程有點複雜,如果要實作延遲加載(後面會講)就隻能用resultMap實作 ,如果為了友善對關聯資訊進行解析,也可以用association将關聯資訊映射到pojo中友善解析。
2.多表間的一對多查詢
2.1需求
查詢所有訂單資訊及訂單下的訂單明細資訊。分析:一個訂單可以可以有多個訂單明細,而一個訂單明細隻屬于一個訂單,是以訂單與訂單明細間的關系為一對多。
2.2建立表和資料
1
2
3
create table orderdetail( id int primary key auto_increment, orders_id int, items_id int, items_num int);//建立訂單明細表
訂單表我們已經建立
建立和訂單明細表對應的pojo對象:
1
2
3
4
5
6
7
8
9
10
11
public class Orderdetail
{
private Integer id;
private Integer ordersId;
private Integer itemsId;
private Integer itemsNum;
}
并建立相關的set和get方法。
2.3sql查詢語句
1.先确定主查詢表:訂單表。2.再确定關聯查詢表:使用者表加訂單明細表。通過orderdetail關聯查詢訂單使用orders_id一個外鍵,隻能關聯查詢出一條訂單記錄,我們使用内連接配接。查詢語句為:
SELECT orders.*,user.username,user.sex ,orderdetail.id orderdetail_id,orderdetail.items_num,orderdetail.items_id
FROM orders,user,orderdetail
WHERE orders.user_id = user.id AND orders.id=orderdetail.orders_id
2.4使用resultMap進行一對多映射
思路:resultMap 提供collection完成關聯資訊映射到集合對象中。在orders類中建立集合屬性:
然後修改OrdersMapperCustom.xml中的資訊:
并在其中添加resultMap的定義:
然後在OrdersMapperCutom.java中添加方法:
最後進行測試:
發現查詢的結果已全部映射到pojo對象Orders.java的屬性中。
3.多對多查詢(以後我會實作的)
首先我們應該明确的是:一對多是多對多的特例。
需求1:查詢顯示字段:使用者賬号、使用者名稱、使用者性别、商品名稱、商品價格(最常見)
企業開發中常見明細清單,使用者購買商品明細清單,
使用resultType将上邊查詢列映射到pojo輸出。
需求2:查詢顯示字段:使用者賬号、使用者名稱、購買商品數量、商品明細(滑鼠移上顯示明細)
使用resultMap将使用者購買的商品明細清單映射到user對象中。
講完如何使用resultMap完成多表間的查詢結果與pojo對象的進階映射,這裡我們還需要補充一個使用resultMap實作延遲加載的知識點。
4.延遲加載
4.1使用延遲加載的意義
在進行資料查詢時,為了提高資料庫查詢性能,盡量使用單表查詢,因為單表查詢比多表關聯查詢速度要快。
如果查詢單表就可以滿足需求,一開始先查詢單表,當需要關聯資訊時,再關聯查詢,當需要關聯資訊再查詢這個叫延遲加載。
mybatis中resultMap提供延遲加載功能,通過resultMap配置延遲加載,但需要在MyBatis的配置檔案中進行相關配置,如下:
4.2配置mybatis支援延遲加載
設定項
描述
允許值
預設值
lazyLoadingEnabled
全局性設定懶加載。如果設為‘false’,則所有相關聯的都會被初始化加載。
true|false
false
aggressiveLazyLoading
當設定為‘true’的時候,懶加載的對象可能被任何懶屬性全部加載。否則,每個屬性都按需加載。
true | false
true
然後在SqlMapperConfig.xml中添加如下配置資訊:
4.3一對一延遲加載的實作
4.3.1實作思路
需求:查詢訂單及使用者的資訊,一對一查詢。
剛開始我們隻查詢訂單資訊。而當需要使用者資訊時調用Orders類中的getUser()方法執行延遲加載 ,向資料庫發出sql。代碼實作如下:
在OrderMapperCustom.xml檔案中添加如下資訊:
并定義resultMap标簽:
然後在OrderMapperCustom.java接口中添加如下方法:
最後是測試代碼:
4.4一對多延遲加載的實作
一對多延遲加載的方法同一對一延遲加載,在collection标簽中配置select内容。
5.resultType、resultMap、延遲加載使用場景總結
延遲加載:
延遲加載實作的方法多種多樣,在隻查詢單表就可以滿足需求,為了提高資料庫查詢性能使用延遲加載,再查詢關聯資訊。
mybatis提供延遲加載的功能用于service層。
resultType:作用:将查詢結果按照sql列名pojo屬性名一緻性映射到pojo中。
場合:常見一些明細記錄的展示,将關聯查詢資訊全部展示在頁面時,此時可直接使用resultType将每一條記錄映射到pojo中,在前端頁面周遊list(list中是pojo)即可。
resultMap:使用association和collection完成一對一和一對多進階映射。
association:作用:将關聯查詢資訊映射到一個pojo類中。
場合:為了友善擷取關聯資訊可以使用association将關聯訂單映射為pojo,比如:查詢訂單及關聯使用者資訊。
collection:作用:将關聯查詢資訊映射到一個list集合中。
場合:為了友善擷取關聯資訊可以使用collection将關聯資訊映射到list集合中,比如:查詢使用者權限範圍子產品和功能,可使用collection将子產品和功能清單映射到list中。