Mybatis學習(四)————— 高階對映,一對一,一對多,多對多對映
一、單向和雙向
包括一對一,一對多,多對多這三種情況,但是每一種又分為單向和雙向,在hibernate中我們就詳細解析過這單向和雙向是啥意思,在這裡,在重複一遍,就拿一對多這種關係來講,比如有員工和部門,一個部門中有多個員工,從部門方看,是一對多關係,而多名員工屬於一個部門,是多對一關係,那麼如果我們的業務需求只需要通過部門查詢到所有的員工,那麼我們就只需要進行單向一對多的對映,如果我們需要通過員工來查詢出對應的部門,那麼我們就需要進行單向多對一的對映,而如果我們這兩個業務需求都需要實現,也就是不管從哪一方進行查詢,都需要能夠找到對方,那麼此時就應該編寫雙向一對多或者雙向多對一(雙向一對多和雙向多對一是一樣的意思)。所以,不管是編寫哪一種,都是根據業務需求來進行決策的。這就是單向和雙向的意思。
什麼是多對多?
多對多就是不管從哪一方看,都是一對多,那麼該關係就是多對多。比如學生跟選修課之間,從學生方看,一個學生能選多門選修課,一對多關係,從選修課之間,一門選修課可以被多個學生選擇,也是一對多關係,那麼學生跟選修課就是多對多關係。多對多關係之間都會由第三張表來表示這種關係。而不會相互設定外來鍵。
二、測試環境
三、一對一對映
有了上面這個關係圖,那我們測試就好做多了,就拿orders 和user來測試,從orders方看向user方,就是一對一對映。也就是單向一對一,只需要根據orders能找出user即可。
兩種方案,對映檔案中輸出對映使用resultType和resultMap。這裡只關注對映檔案,全域性配置檔案就不多說了,還是老樣子的配置
3.1、使用resultType
UserMapper.xml
UserExt.java
因為需要在查詢orders時,將對應的user也查詢出來,那麼使用resultType的話,就需要建立一個OrdersExt,將user和orders中的屬性合併在一起,形成一個新的pojo。這樣就能夠將查詢出來的記錄都對映到該pojo上了
3.2、使用resultMap
usermapper.xml
resultMap
使用resultMap的話就不需要構造一個新的pojo,只需要將查詢出來的記錄的值通過resultMap幫我們對映到指定到哪個pojo的哪個屬性上即可。
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="com.wuhao.onetoone.resultMap.UserMapper"> 6 <!-- 7 resultMap 8 type:返回物件型別。全限定名,如果使用了typeAliases設定別名,則可以使用別名 9 id:唯一標識,供下面使用 10 id標籤:唯一標識位,也就是主鍵。 11 column:從資料庫中查詢出來的列名。有時候會使用別名,主要看sql語句返回的列名是什麼 12 property:對應返回物件中屬性名 13 result標籤:對映普通屬性 14 column和property跟上面一樣的功能 15 --> 16 <resultMap type="com.wuhao.onetoone.resultMap.Orders" id="findOrdersAndUserReM"> 17 <id column="oid" property="id"/> 18 <result column="number" property="number"/> 19 <result column="user_id" property="userId"/> 20 <result column="createtime" property="createtime"/> 21 <!-- 使用者資訊, 22 association:一對一對映 23 property:把關聯查詢的一對一的資訊封裝到哪個物件屬性上 24 javaType:property屬性的型別 25 其他的什麼id,result標籤都跟上面的一樣。 26 --> 27 <association property="user" javaType="com.wuhao.onetoone.resultMap.User"> 28 <id column="uid" property="id"/> 29 <result column="username" property="username"/> 30 <result column="sex" property="sex"/> 31 </association> 32 </resultMap> 33 34 <!-- 35 使用resultMap就能夠解決這種麻煩,因為resultMap能進行高階對映,說是高階對映,其實就是可以將查詢出來的列表對映到特定 36 的屬性上去。 37 使用resultMap之後,就會知道resultType的區別在哪裡了 38 resultType:簡單一些,是一種平鋪式的對映,不用層級式對映用這個比較好。需要什麼查什麼 39 resultMap:比較繁瑣,是一種層級式的對映,在企業中如果沒有特殊要求,建議使用resultType來完成一對一對映, 40 --> 41 <select id="findOrdersAndUserByOid" parameterType="int" resultMap="findOrdersAndUserReM"> 42 SELECT 43 orders.id oid, 44 orders.number, 45 orders.user_id, 46 orders.createtime, 47 user.id uid, 48 user.username, 49 user.sex 50 FROM orders,user WHERE orders.id = #{id} AND orders.user_id = user.id 51 </select> 52 53 54 </mapper>
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="com.wuhao.onetoone.resultMap.UserMapper"> 6 <!-- 7 resultMap 8 type:返回物件型別。全限定名,如果使用了typeAliases設定別名,則可以使用別名 9 id:唯一標識,供下面使用 10 id標籤:唯一標識位,也就是主鍵。 11 column:從資料庫中查詢出來的列名。有時候會使用別名,主要看sql語句返回的列名是什麼 12 property:對應返回物件中屬性名 13 result標籤:對映普通屬性 14 column和property跟上面一樣的功能 15 --> 16 <resultMap type="com.wuhao.onetoone.resultMap.Orders" id="findOrdersAndUserReM"> 17 <id column="oid" property="id"/> 18 <result column="number" property="number"/> 19 <result column="user_id" property="userId"/> 20 <result column="createtime" property="createtime"/> 21 <!-- 使用者資訊, 22 association:一對一對映 23 property:把關聯查詢的一對一的資訊封裝到哪個物件屬性上 24 javaType:property屬性的型別 25 其他的什麼id,result標籤都跟上面的一樣。 26 --> 27 <association property="user" javaType="com.wuhao.onetoone.resultMap.User"> 28 <id column="uid" property="id"/> 29 <result column="username" property="username"/> 30 <result column="sex" property="sex"/> 31 </association> 32 </resultMap> 33 34 <!-- 35 使用resultMap就能夠解決這種麻煩,因為resultMap能進行高階對映,說是高階對映,其實就是可以將查詢出來的列表對映到特定 36 的屬性上去。 37 使用resultMap之後,就會知道resultType的區別在哪裡了 38 resultType:簡單一些,是一種平鋪式的對映,不用層級式對映用這個比較好。需要什麼查什麼 39 resultMap:比較繁瑣,是一種層級式的對映,在企業中如果沒有特殊要求,建議使用resultType來完成一對一對映, 40 --> 41 <select id="findOrdersAndUserByOid" parameterType="int" resultMap="findOrdersAndUserReM"> 42 SELECT 43 orders.id oid, 44 orders.number, 45 orders.user_id, 46 orders.createtime, 47 user.id uid, 48 user.username, 49 user.sex 50 FROM orders,user WHERE orders.id = #{id} AND orders.user_id = user.id 51 </select> 52 53 54 </mapper>
3.3、小總結
現在應該認識到了resultMap和resultType的區別,需要知道resultMap中一對一對映時是怎麼編寫這種對映關係的。
上面所側重的重點在對映檔案statement的編寫,
四、一對多對映
查詢訂單資訊,關聯查詢它的訂單明細資訊,orders --》 ordersdetail。 單向一對多關係,一個訂單有多個訂單項。
4.1、使用resultType
使用resultType也可以,按照前面的學習,需要構建一個新的pojo,其中包含了訂單項屬性和orders屬性。這個很簡單,而且都會做,就不多說了,主要說說使用resultMap的用法。
4.2、使用resultMap
其中注意resultMap中的extends的用法,繼承一個resultMap,就把其中的所有配置都繼承過來了,所以這裡只需要編寫一個collection,對映ordersdetail集合。
pojo類中應該多了一個這個東西
這裡主要是關注,一對多時,resultMap中是如何實現的。使用collection。
五、多對多對映
查詢使用者資訊,以及它所購買的商品資訊 user --》 items
主表:user
從表:orders、orderdetail、items
也就是通過查詢某個user,查詢到orders,通過orders查詢到orderdetail,通過orderdetail查詢到items。
pojo
一個使用者擁有多個訂單
一個訂單可以擁有多個訂單明細
一個訂單明細對應一個商品
usermapper.xml
通過上面pojo和sql語句,可以知道,我們寫的resultMap看起來好像需要很複雜,其實不然,一步步一層層進行編寫,也不難。
如果是一對多關係,那麼就使用collection,如果是一對一,那麼就使用association,先寫user到orders,然後在寫orders中的orderdetail,等等,這樣一層層巢狀進去,也很明瞭。不難懂。
六、總結
6.1、resultType和resultMap都可以完成高階結果對映
如果沒有特殊要求,使用resultType方便
6.2、resultType和resultMap 的一個主要區別就是要應用場景不同
resultType主要是查詢明細使用
resultMap主要是層級查詢使用,比如查詢使用者資訊,如何點選查詢訂單,再去查詢訂單資訊
resultMap可以實現延遲載入,而resultType沒有該功能
6.3、延遲載入就是我們下一章節要說的東西,這裡就需要注意,resultMap菜可以實現延遲載入,那麼什麼是延遲載入呢?比如上面一對一關係中,通過orders查詢到對應的user,當沒有使用到user時,那麼orders是不會查詢出user的,等當使用user時,才會進行查詢載入,這就是延遲載入,也稱為懶載入,具體下一節講解。下一節還會講解一級快取,二級快取的問題。