mybatis 一對一查詢的兩種方式的實現,較為詳細。歡迎新手學習及大神指導。 ...
所謂的一對一查詢,就是說我們在查詢一個表的數據的時候,需要關聯查詢其他表的數據。
需求
首先說一個使用一對一查詢的小需求吧:假設我們在查詢某一個訂單的信息的時候,需要關聯查詢出創建這個訂單對應的用戶信息。表模型如下(
ResultType
sql語句的書寫
首先,我們要對我們的需求進行分析。1.我們需要確定這個需求需要涉及到哪兩張表,其中哪個是主表,哪個是關聯表。具體怎麼確定,還是看需求——我們的需求是說,在查詢訂單的時候,順帶著查出創建這個訂單的用戶。那麼,已經很顯然了。我們的主表是訂單表(orders)。而我們的關聯表則是用戶表(user)。
這個時候,我們就可以寫出來如下sql語句了:
select * from orders
這個時候,我們就應該考慮這個問題了:我們在關聯查詢的時候應該使用內鏈接?還是外鏈接?對於搞不清內鏈接外鏈接的區別的同學,我這裡先簡單的介紹一下,等以後有時間了,再詳細寫一篇博客說明:內連接是只顯示滿足條件的。外鏈接分為左外和右外鏈接:左連接顯示左邊全部的再加上右邊與左邊相同的;右連接顯示右邊全部的和左邊與右邊相同的。
我們的需求是通過訂單去關聯用戶,而由於在orders表中有一個外鍵(userId)。通過外鍵的去查關聯表user表的數據時,userId是user表的主鍵。這時,只能查到一條user的信息,而這條記錄不會導致我們的主查詢結果發生改變。所以,我們選擇內鏈接查詢。這時候,我們的sql語句是這樣的:
select * from orders,user where orders.user_id = user.id
查詢完成後,出現結果如下:
這時,問題來了,我們發現,這個時候出現了兩個id,這就會導致我們的數據在輸出的時候封裝到對象時會出現問題。而且,User_id 這一列和我們的用戶id數據是重覆的。我們需要改造我們的sql。怎麼改造呢?
因為我們的主表數據是要全部查詢的,而用戶表我們只需要username,sex,adress這三個信息(這裡是假設,沒必要糾結需要的是啥信息)。那麼我們就需要手動指定我們的sql語句的查詢欄位了:
1 SELECT 2 orders.*, 3 USER.username, 4 USER.sex, 5 USER.address 6 FROM 7 orders, 8 USER 9 WHERE orders.user_id = user.id最終的sql語句
前面的這些都是在我們的sql鏈接工具上進行查詢的,當可以顯示我們需要的資料庫後,我們的sql語句就確定了。這時我們該開始下一步了:
創建pojo
我們需要將查詢到的結果,通過mybatis框架將數據封裝到對應的對象。那麼,問題來了,這個查詢到的數據由誰來接收?我們如果要將上邊sql查詢的結果映射到pojo中,pojo中必須包括所有查詢列名。但是不管是原來的Orders類還是User類,都沒有辦法映射全部的欄位。這時,我們有一個很簡單的解決辦法:根據返回的欄位,專門寫一個類,讓它包含所有的查詢結果,然後讓這個類去接收這個返回的結果集。
這時有個小技巧,我們的新的pojo中,不需要將所有的欄位全部都寫上,我們可以讓新pojo去繼承我們的包含結果集中查詢欄位較多的一個類,然後將其他需要的數據寫到這個子類中即可。
創建pojo完成後,我們就需要根據規範去創建我們的映射文件和寫對應的介面中的方法:
mapper.xml
mapper.java中的介面:
ResultMap
sql語句上,resultType 和resuleMap實現的方式一樣,這裡就直接跳過了。
使用resultMap映射的思路
我們知道,使用pojo的時候,我們可以將一些數據封裝到pojo的對象屬性中,他的屬性可以是簡單類型,也可以是另外一個pojo。這時,我們可以這麼做:
使用resultMap將查詢結果中的訂單信息映射到Orders對象中,在orders類中添加User屬性,將關聯查詢出來的用戶信息映射到orders對象中的user屬性中。
Orders類中添加user屬性
mapper.xml
用resultMap的方法將結果集進行映射的時候,我們需要進行兩個操作,一個是定義resultMap,設置每個查到的結果集中的列相對應的對象的屬性。這個比較麻煩但是不難。二就是定義我們的statement。
resultMap
resultMap實現的基本思路我們剛纔已經說了。而且也在orders的pojo類中增加了相應的屬性了。接下啦,就是寫一個resultMap,將整個查詢的結果映射到Orders中在這裡面,首先是order訂單的映射。就是直接用id 和result標簽將兩者相互對應即可。然後就是,關聯的用戶信息的映射,這時候需要用到一個association的標簽,將在orders類中的user欄位與User類進行映射,然後在其內部還是用id和result標簽,將查詢的數據和User的屬性相映射。
具體代碼如下:
1 <!-- 訂單查詢關聯用戶的resultMap 2 將整個查詢的結果映射到cn.mybatis.po.Orders中 3 --> 4 <resultMap type="cn.mybatis.po.Orders" id="OrdersUserResultMap"> 5 <!-- 配置映射的訂單信息 --> 6 <!-- id:指定查詢列中的唯 一標識,訂單信息的中的唯 一標識,如果有多個列組成唯一標識,配置多個id 7 column:訂單信息的唯 一標識 列 8 property:訂單信息的唯 一標識 列所映射到Orders中哪個屬性 9 --> 10 <id column="id" property="id"/> 11 <result column="user_id" property="userId"/> 12 <result column="number" property="number"/> 13 <result column="createtime" property="createtime"/> 14 <result column="note" property=note/> 15 16 <!-- 配置映射的關聯的用戶信息 --> 17 <!-- association:用於映射關聯查詢單個對象的信息 18 property:要將關聯查詢的用戶信息映射到Orders中哪個屬性 19 --> 20 <association property="user" javaType="cn.mybatis.po.User"> 21 <!-- id:關聯查詢用戶的唯 一標識 22 column:指定唯 一標識用戶信息的列 23 javaType:映射到user的哪個屬性 24 --> 25 <id column="user_id" property="id"/> 26 <result column="username" property="username"/> 27 <result column="sex" property="sex"/> 28 <result column="address" property="address"/> 29 30 </association> 31 </resultMap>resultMap代碼
statement
statement比較簡單,就是將返回結果集的映射方式改成resultMap。然後將返回類型只想我們剛完成的resultMap就可以了。
mapper.java
兩者的區別
實現一對一查詢的方法說完了,接下來分析下它們的不同之處,和優劣之處。
首先,都需要對pojo進行修改,一個是增加一個pojo類另外一個則是修改pojo的欄位。個人感覺,根據設計模式中的開閉原則。resultType要比resultMap更好一些。
其次,簡易程度上來說,使用resultType實現較為簡單。從這點講,resultType也要比resultMap更好一些。
不過resultMap可以實現延遲載入,resultType無法實現延遲載入。這方面resultType就不如resultMap更好了。
所以:建議大家,如果沒有查詢結果的特殊要求的話使用resultType。