mybatis第二天 高級映射 查詢緩存 和spring整合

1. 訂單商品數據模型

2. 一對一查詢

2.1 需求

查詢訂單信息,關聯查詢創建訂單的用戶信息
實現方式包括:
resultType:需要新的返回值包裝對象
resultMap:不需要新的返回值包裝,但是過程麻煩點。
區別
resultType:使用resultType實現較爲簡單,如果pojo中沒有包括查詢出來的列名,需要增加列名對應的屬性,即可完成映射。
如果沒有查詢結果的特殊要求建議使用resultType

resultMap:需要單獨定義resultMap,實現有點麻煩,如果對查詢結果有特殊的要求,使用resultMap可以完成將關聯查詢映射pojo的屬性中。

resultMap可以實現延遲加載,resultType無法實現延遲加載。

2.2 resultType

(1)SQL語句

SELECT 
  orders.*,
  USER.username,
  USER.sex,
  USER.address 
FROM
  orders,
  USER 
WHERE orders.user_id = user.id

(2)創建pojo
上面查詢的結果無法映射到現有的pojo中,索引需要創建新的pojo。
這裏創建一個pojo繼承包括查詢結果字段較多的類。
在這裏插入圖片描述
(3)mapper.xml
基於sql和返回類,寫出完整的mapper映射文件
在這裏插入圖片描述
(4)mapper.java
寫出mappper.xml對應的接口
在這裏插入圖片描述
(5)在SqlMapConfig.xml加載映射文件

2.3 resultMap

(1)思路:使用resultMap將查詢結果中的訂單信息映射到Orders對象中,在orders類中添加User屬性,將關聯查詢出來的用戶信息映射到orders對象中的user屬性中。
(2)在Orders類增加屬性user對象
在這裏插入圖片描述
(3)準備mapper.xml文件
定義resultMap
訂單查詢關聯用戶的resultMap將整個查詢的結果映射到cn.itcast.mybatis.po.Orders中
屬性user的配置使用:<association property="user" javaType="cn.itcast.mybatis.po.User">

<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserResultMap">
	<!-- 配置映射的訂單信息 -->
	<!-- id:指定查詢列中的唯一標識,訂單信息的中的唯一標識,如果有多個列組成唯一標識,配置多個id
		column:訂單信息的唯一標識列
		property:訂單信息的唯一標識列所映射到Orders中哪個屬性
	  -->
	<id column="id" property="id"/>
	<result column="user_id" property="userId"/>
	<result column="number" property="number"/>
	<result column="createtime" property="createtime"/>
	<result column="note" property=note/>
	
	<!-- 配置映射的關聯的用戶信息 -->
	<!-- association:用於映射關聯查詢單個對象的信息
	property:要將關聯查詢的用戶信息映射到Orders中哪個屬性-->
	<association property="user"  javaType="cn.itcast.mybatis.po.User">
		<!-- id:關聯查詢用戶的唯 一標識
		column:指定唯 一標識用戶信息的列
		javaType:映射到user的哪個屬性
		 -->
		<id column="user_id" property="id"/>
		<result column="username" property="username"/>
		<result column="sex" property="sex"/>
		<result column="address" property="address"/>
	</association>
</resultMap>

statement

在這裏插入圖片描述

(4)mapper.java
在這裏插入圖片描述

3. 一對多查詢

需求:查詢訂單及訂單明細的信息
難點:查詢到的結果是一部分屬性值是重複的。
方案

  • resultMap:使用collection對關聯查詢的多條記錄映射到一個list集合屬性中。
  • resultType:將訂單明細映射到orders中的orderdetails中,需要自己處理,使用雙重循環遍歷,去掉重複記錄,將訂單明細放在orderdetails中。

3.1 SQL語句

確定主查詢表:訂單表
確定關聯查詢表:訂單明細表
在一對一查詢基礎上添加訂單明細表關聯即可。

SELECT 
  orders.*,
  USER.username,
  USER.sex,
  USER.address,
  orderdetail.id orderdetail_id,   // 這裏的id和前面的重複了,需要設別名
  orderdetail.items_id,
  orderdetail.items_num,
  orderdetail.orders_id
FROM
  orders,
  USER,
  orderdetail
WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id

上述語句得到的結果是重複的。
在這裏插入圖片描述

3.2 在orders中添加list訂單明細屬性

在orders.java類中添加List orderDetails屬性。
最終會將訂單信息映射到orders中,訂單所對應的訂單明細映射到orders中的orderDetails屬性中。
在這裏插入圖片描述

3.3 mapper.xml

resultMap定義:
列表標籤:<collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">

<!-- 訂單及訂單明細的resultMap使用extends繼承,不用在中配置訂單信息和用戶信息的映射->
	<resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersAndOrderDetailResultMap" extends="OrdersUserResultMap">
		<!-- 訂單信息 -->
		<!-- 用戶信息 -->
		<!-- 使用extends繼承,不用在中配置訂單信息和用戶信息的映射 -->
		
		<!-- 訂單明細信息
		一個訂單關聯查詢出了多條明細,要使用collection進行映射
		collection:對關聯查詢到多條記錄映射到集合對象中
		property:將關聯查詢到多條記錄映射到cn.itcast.mybatis.po.Orders哪個屬性
		ofType:指定映射到list集合屬性中pojo的類型
		 -->
		 <collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
		 	<!-- id:訂單明細唯 一標識
		 	property:要將訂單明細的唯 一標識 映射到cn.itcast.mybatis.po.Orderdetail的哪個屬性
		 	  -->
		 	<id column="orderdetail_id" property="id"/>
		 	<result column="items_id" property="itemsId"/>
		 	<result column="items_num" property="itemsNum"/>
		 	<result column="orders_id" property="ordersId"/>
		 </collection>
	</resultMap>

mapper.xml:
在這裏插入圖片描述

3.4 mapper.java

在這裏插入圖片描述

4. 多對多查詢

查詢用戶及用戶購買商品信息,多對多關係

4.1 SQL

SELECT 
  orders.*,
  USER.username,
  USER.sex,
  USER.address,
  orderdetail.id orderdetail_id,
  orderdetail.items_id,
  orderdetail.items_num,
  orderdetail.orders_id,
  items.name items_name,
  items.detail items_detail,
  items.price items_price
FROM
  orders,
  USER,
  orderdetail,
  items
WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id AND orderdetail.items_id = items.id

4.2 mapper.xml

resultMap

<!-- 查詢用戶及購買的商品 -->
	<resultMap type="cn.itcast.mybatis.po.User" id="UserAndItemsResultMap">
		<!-- 用戶信息 -->
		<id column="user_id" property="id"/>
		<result column="username" property="username"/>
		<result column="sex" property="sex"/>
		<result column="address" property="address"/>
		<!-- 訂單信息一個用戶對應多個訂單,使用collection映射-->
		 <collection property="ordersList" ofType="cn.itcast.mybatis.po.Orders">
		 	<id column="id" property="id"/>
		 	<result column="user_id" property="userId"/>
			<result column="number" property="number"/>
			<result column="createtime" property="createtime"/>
			<result column="note" property="note"/>
			 <!-- 訂單明細 一個訂單包括 多個明細-->
		  	<collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
		  			<id column="orderdetail_id" property="id"/>
				 	<result column="items_id" property="itemsId"/>
				 	<result column="items_num" property="itemsNum"/>
				 	<result column="orders_id" property="ordersId"/>
				 	<!-- 商品信息一個訂單明細對應一個商品-->
			  	 	<association property="items" javaType="cn.itcast.mybatis.po.Items">
			  	 		<id column="items_id" property="id"/>
			  	 		<result column="items_name" property="name"/>
			  	 		<result column="items_detail" property="detail"/>
			  	 		<result column="items_price" property="price"/>
			  	 	</association>
		  	</collection>
		 </collection>
</resultMap>

mapper.xml
在這裏插入圖片描述

4.3 mapper.java

在這裏插入圖片描述

4.4 多對多查詢總結

一對多是多對多的特例,如下需求:
查詢用戶購買的商品信息,用戶和商品的關係是多對多關係。
需求1:
查詢字段:用戶賬號、用戶名稱、用戶性別、商品名稱、商品價格(最常見)
企業開發中常見明細列表,用戶購買商品明細列表,
使用resultType將上邊查詢列映射到pojo輸出。

需求2:
查詢字段:用戶賬號、用戶名稱、購買商品數量、商品明細(鼠標移上顯示明細)
使用resultMap將用戶購買的商品明細列表映射到user對象中。

總結:
使用resultMap是針對那些對查詢結果映射有特殊要求的功能,比如特殊要求映射成list中包括 多個list。

4.5 resultMap總結

  • resultType:
    作用:將查詢結果按照sql列名pojo屬性名一致性映射到pojo中。
    場合:常見一些明細記錄的展示,比如用戶購買商品明細,將關聯查詢信息全部展示在頁面時,此時可直接使用resultType將每一條記錄映射到pojo中,在前端頁面遍歷list(list中是pojo)即可。
  • resultMap:
    使用association和collection完成一對一和一對多高級映射(對結果有特殊的映射要求)。
    association
    作用:將關聯查詢信息映射到一個pojo對象中。
    場合:爲了方便查詢關聯信息可以使用association將關聯訂單信息映射爲用戶對象的pojo屬性中,比如:查詢訂單及關聯用戶信息。
    使用resultType無法將查詢結果映射到pojo對象的pojo屬性中,根據對結果集查詢遍歷的需要選擇使用resultType還是resultMap。
    collection
    作用:將關聯查詢信息映射到一個list集合中。
    場合:爲了方便查詢遍歷關聯信息可以使用collection將關聯信息映射到list集合中,比如:查詢用戶權限範圍模塊及模塊下的菜單,可使用collection將模塊映射到模塊list中,將菜單列表映射到模塊對象的菜單list屬性中,這樣的作的目的也是方便對查詢結果集進行遍歷查詢。
    如果使用resultType無法將查詢結果映射到list集合中。

5. resultMap實現延遲加載

當需要查詢關聯信息時再去數據庫查詢,默認不去關聯查詢,提高數據庫性能。
只有使用resultMap支持延遲加載設置。

5.1 打開延遲加載設置

在mybatis核心配置文件中配置:

<settings>
	<setting name="lazyLoadingEnabled" value="true"/>
	<setting name="aggressiveLazyLoading" value="false"/>
</settings>

5.2 Mapper.java

public List<Orders> findOrdersList3() throws Exception;

5.3 Mapper.xml

(1)定義resultMap

<!-- 訂單信息resultmap -->
<resultMap type="cn.itcast.mybatis.po.Orders" id="userordermap2">
	<id property="id" column="id"/>
	<result property="user_id" column="user_id"/>
	<result property="number" column="number"/>
	<association property="user" javaType="cn.itcast.mybatis.po.User" select="findUserById" column="user_id"/>   <!-- 子對象需要新的函數findUserById -->
</resultMap>

association實現延遲加載:
select="findUserById":指定關聯查詢sql爲findUserById
column="user_id":關聯查詢時將users_id列的值作爲參數傳入findUserById方法,最後將關聯查詢結果映射至cn.itcast.mybatis.po.User。
(2)定義sql語句

<select id="findOrdersList3" resultMap="userordermap2">
	SELECT orders.*	FROM orders
</select>

5.4 測試

List<Orders> list = userMapper.findOrdersList3();

5.5 手動實現延遲加載?

針對訂單和用戶兩個表定義兩個mapper方法,分步執行。
1、訂單查詢mapper方法
2、根據用戶id查詢用戶信息mapper方法
默認使用訂單查詢mapper方法只查詢訂單信息。
當需要關聯查詢用戶信息時再調用根據用戶id查詢用戶信息mapper方法查詢用戶信息。

6.mybatis整合encache

不適用分佈式緩存,則緩存的數據在各個服務器分開存放,不方便系統開發。而mybatis不支持分佈式緩存,故需要和其他框架進行整合。

6.1 整合方法(掌握)

mybatis提供了一個cache接口,如果要實現自己的緩存邏輯,實現cache接口開發即可。
(1)導包
在這裏插入圖片描述
(2)爲指定的接口配置cache接口的實現類
在mapper.xml中配置,開啓緩存:
在這裏插入圖片描述
(3)在classpath下配置encache.xml
指定緩存的配置參數:
在這裏插入圖片描述

6.2二級緩存的應用場景

應用場景:對於訪問多的查詢請求且用戶對查詢結果實時性要求不高,此時可採用mybatis二級緩存技術降低數據庫訪問量,提高訪問速度,業務場景比如:耗時較高的統計分析sql、電話賬單查詢sql等。
實現方法:通過設置刷新間隔時間,由mybatis每隔一段時間自動清空緩存,根據數據變化頻率設置緩存刷新間隔flushInterval。

6.3二級緩存的侷限性

mybatis二級緩存對細粒度的數據級別的緩存實現不好。
比如如下需求:對商品信息進行緩存,由於商品信息查詢訪問量大,但是要求用戶每次都能查詢最新的商品信息,此時如果使用mybatis的二級緩存就無法實現當一個商品變化時只刷新該商品的緩存信息而不刷新其它商品的信息,因爲mybaits的二級緩存區域以mapper爲單位劃分,當一個商品信息變化會將所有商品信息的緩存數據全部清空。
解決此類問題需要在業務層根據需求對數據有針對性緩存。

7. 與spring整合

7.1 原始dao開發(和spring整合後)

先創建applicationContext對象,然後獲得userDao對象。
userDao對象的創建需要先創建sqlSessinFactory對象;
sqlSessinFactory對象的創建需要SqlMapConfig.xml配置文件提供SQL語句和dataSource數據源對象提供數據庫參數;
dataSource的參數從db.properties獲得;
然後可調用userDao對象的findUserById方法,這個方法通過調過sqlSession調用配置的"test.findUserById"SQL語句實現功能。

  • 先寫出需要實現的SQL:User.xml,然後在SqlMapconfig.xml中加載User.xml
  • 上面的XML文件用於dao實現類調用,創建dao實現類(繼承SqlSessionDaoSupport)。dao接口實現類需要注入SqlSessoinFactory,通過spring進行注入。
  • 這裏spring聲明配置方式,在applicationContext.xml中配置dao。

7.2 mapper代理開發

(1)mapper.xml和mapper.java
(2)通過MapperFactoryBean創建代理對象

在這裏插入圖片描述
此方法問題:
需要針對每個mapper進行配置,麻煩。
(3)測試
(4)通過MapperScannerConfigurer進行mapper掃描(建議使用),創建代理對象
在這裏插入圖片描述

8 逆向工程(會用)

mybaits需要程序員自己編寫sql語句,mybatis官方提供逆向工程 可以針對單表自動生成mybatis執行所需要的代碼(mapper.java,mapper.xml、po…)

企業實際開發中,常用的逆向工程方式:
由於數據庫的表生成java代碼。
導包:
在這裏插入圖片描述
【資料整理自網上】

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章