天氣甚好,怎能不學習?
一、單向和雙向
包括一對一,一對多,多對多這三種情況,但是每一種又分為單向和雙向,在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>
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時,才會進行查詢加載,這就是延遲加載,也稱為懶加載,具體下一節講解。下一節還會講解一級緩存,二級緩存的問題。
