mybatis延遲載入和快取
一、mybatis延遲載入
1、延遲載入概述
(1)延遲載入又叫懶載入,也叫按需載入。也就是說先載入主資訊,在需要的時候,再去載入從資訊
(2)在mybatis中,resultMap標籤 的association標籤和collection標籤具有延遲載入的功能。
2、延遲載入案例分析
(1)需求:查詢訂單資訊,關聯查詢使用者資訊
a、建立一個statement來查詢訂單資訊
b、建立一個statement來查詢使用者資訊
(2)對映檔案:
<!-- lazyLoadingRstMap -->
<resultMap type="ordersExt" id="lazyLoadingRstMap">
<!-- 訂單資訊 -->
<id column="id" property="id" />
<result column="user_id" property="userId" />
<result column="number" property="number" />
<!-- 使用者資訊(一對一) -->
<!-- select:指定關聯查詢的查詢statement(即查詢使用者的statement的id),然後將查詢結果,封裝到property屬性指定的變數中 -->
<!-- column:通過column指定的列所查詢出的結果,作為select指的statement的入參 -->
<!-- 注意:如果select指定的statement,入參需要多個值,需要在column中{col1=prop1,col2=prop2} -->
<association property="user"
select="com.san.mapper.UserMapper.findUserById" column="user_id"></association>
</resultMap>
<!-- 延遲載入 -->
<select id="findOrderAndUserLazyLoading" resultMap="lazyLoadingRstMap">
SELECT * FROM
orders
</select>
建立查詢使用者資訊的對映檔案:
<!-- 根據使用者ID查詢使用者資訊 -->
<select id="findUserById" parameterType="int" resultType="com.san.po.User">
SELECT
* FROM USER WHERE id =#{id}
</select>
(3)mapper介面:
//延遲載入
public List<OrdersExt> findOrderAndUserLazyLoading();
(4)測試程式碼:
//懶載入
@Test
public void Test01() throws IOException{
// 讀取配置檔案
// 全域性配置檔案的路徑
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 建立SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 建立OrdersMapper物件
SqlSession sqlSession = sqlSessionFactory.openSession();
OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);
List<OrdersExt> list = mapper.findOrderAndUserLazyLoading();
//按需載入時,是需要的時候再去查詢資料庫
for (OrdersExt ordersExt : list) {
System.out.println(ordersExt.getUser());
}
sqlSession.close();
}
(5)設定延遲載入:
在SqlMapConfig.xml中,配置settings標籤
<settings>
<!-- 開啟延遲載入 ,預設值為true-->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 設定積極的懶載入,預設是true -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 二級快取的總開關 -->
<setting name="cacheEnabled" value="true"/>
</settings>
二、mybatis一級快取
1、mybatis快取理解
(1)Mybatis的快取,包括一級快取和二級快取,一級快取是預設使用的,二級快取需要手動開啟。
(2)一級快取指的就是sqlsession,在sqlsession中有一個資料區域,是map結構,這個區域就是一級快取區域。一級快取中的key是由sql語句、條件、statement等資訊組成一個唯一值。一級快取中的value,就是查詢出的結果物件。
(3)二級快取指的就是同一個namespace下的mapper,二級快取中,也有一個map結構,這個區域就是一級快取區域。一級快取中的key是由sql語句、條件、statement等資訊組成一個唯一值。一級快取中的value,就是查詢出的結果物件。
(4)圖解:
2、一級快取原理
3、一級快取測試
(1)測試1:
@Test
//一級快取測試1
public void Test01() throws Exception{
//全域性配置檔案
String resource="SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//建立Mapper物件
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//第一次查詢
User user1=userMapper.findUserById(1);
System.out.println(user1);
//第二次查詢
User user2=userMapper.findUserById(1);
System.out.println(user2);
//關閉資源
sqlSession.close();
}
(2)測試2:
@Test
//一級快取測試2
public void Test02() throws Exception{
//全域性配置檔案
String resource="SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//建立mapper物件
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//第一次查詢
User user1=mapper.findUserById(1);
System.out.println(user1);
//執行新增使用者操作
mapper.insertUser(user1);
//執行commit操作,將一級快取清空
sqlSession.commit();
//第二次查詢
User user2=mapper.findUserById(1);
System.out.println(user2);
}
(3)解釋:
三、mybatis二級快取
1、二級快取原理
2、二級快取測試
(1)開啟二級快取:
a、開啟二級快取的總開關
<!-- 二級快取的總開關 -->
<setting name="cacheEnabled" value="true"/>
b、在mapper對映檔案中開啟二級快取
<!-- 開啟二級快取,預設使用PerpetualCache -->
<cache/>
(2)序列化:
二級快取,需要序列化是因為需要將快取的資料寫入硬碟
public class User implements Serializable
(3)測試1:
@Test
//二級快取測試1
public void Test01() throws Exception{
String resource="SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
SqlSession sqlSession3 = sqlSessionFactory.openSession();
//由mybatis通過sqlSession來建立代理物件
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
UserMapper mapper3 = sqlSession3.getMapper(UserMapper.class);
//第一次查詢
User user1=mapper1.findUserById(1);
System.out.println(user1);
//在close的時候,才會將資料寫入二級快取中
sqlSession1.close();
//第二次查詢
User user2=mapper2.findUserById(1);
System.out.println(user2);
sqlSession2.close();
}
(4)測試2:
@Test
//二級快取測試2
public void Test02() throws Exception{
String resource="SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
SqlSession sqlSession3 = sqlSessionFactory.openSession();
//由mybatis通過sqlSession來建立代理物件
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
UserMapper mapper3 = sqlSession3.getMapper(UserMapper.class);
//第一次查詢
User user1=mapper1.findUserById(1);
System.out.println(user1);
//在close的時候,才會將資料寫入二級快取中
sqlSession1.close();
//執行使用者新增操作
mapper3.insertUser(user1);
//執行commit時,將一級快取清空
sqlSession3.close();
//第二次查詢
User user2=mapper2.findUserById(1);
//System.out.println(user2);
sqlSession2.close();
}
3、其他
(1)禁用快取:
useCache=”false”
<select id="findUserById" useCache="false" parameterType="int" resultType="com.san.po.User">
SELECT
* FROM USER WHERE id =#{id}
</select>
(2)重新整理快取:
flushCache=”true”:重新整理快取,在select語句中,預設值是false,在增刪改語句中,預設值是true
<select id="findUserById" flushCache="true" parameterType="int" resultType="com.san.po.User">
SELECT
* FROM USER WHERE id =#{id}
</select>
四、整合ehcache
1、ehcache概述
(1)Ehcache是一個分散式的快取框架
(2)Mybatis本身是一個持久層框架,它不是專門的快取框架,所以它對快取的實現不夠好,不能支援分散式。
2、分散式概述
(1)系統為了提高效能,通常會對系統採用分散式部署(叢集部署方式)
(2)圖解:
3、整合思路
(1)Cache是一個介面,它的預設實現是mybatis的PerpetualCache。如果想整合mybatis的二級快取,那麼實現Cache介面即可
(2)圖解:
4、整合步驟
(1)新增jar包
(2)設定對映檔案中cache標籤的type值為ehcache的實現類
(3)新增ehcache的配置檔案
在config下,建立ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<!-- 快取資料要存放的磁碟地址 -->
<diskStore path="F:\develop\ehcache" />
<!-- diskStore:指定資料在磁碟中的儲存位置。
defaultCache:當藉助CacheManager.add("demoCache")建立Cache時,
EhCache便會採用<defalutCache/>指定的的管理策略
以下屬性是必須的: maxElementsInMemory - 在記憶體中快取的element的最大數目
maxElementsOnDisk - 在磁碟上快取的element的最大數目,若是0表示無窮大
eternal - 設定快取的elements是否永遠不過期。如果為true,則快取的資料始終有效,
如果為false那麼還要根據timeToIdleSeconds,timeToLiveSeconds判斷
overflowToDisk - 設定當記憶體快取溢位的時候是否將過期的element快取到磁碟上 以下屬性是可選的:
timeToIdleSeconds - 當快取在EhCache中的資料前後兩次訪問的時間超過timeToIdleSeconds的屬性取值時,
這些資料便會刪除,預設值是0,也就是可閒置時間無窮大
timeToLiveSeconds - 快取element的有效生命期,預設是0.,
也就是element存活時間無窮大 diskSpoolBufferSizeMB
這個引數設定DiskStore(磁碟快取)的快取區大小.預設是30MB.每個Cache都應該有自己的一個緩衝區.
diskPersistent - 在VM重啟的時候是否啟用磁碟儲存EhCache中的資料,預設是false。
diskExpiryThreadIntervalSeconds - 磁碟快取的清理執行緒執行間隔,預設是120秒。
每個120s,相應的執行緒會進行一次EhCache中資料的清理工作 memoryStoreEvictionPolicy
- 當記憶體快取達到最大,有新的element加入的時候, 移除快取中element的策略。預設是LRU(最近最少使用),
可選的有LFU(最不常使用)和FIFO(先進先出) -->
<defaultCache maxElementsInMemory="1000"
maxElementsOnDisk="10000000" eternal="false" overflowToDisk="false"
timeToIdleSeconds="120" timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
5、其他
(1)應用場景:
對於訪問響應速度要求高,但是實時性不高的查詢,可以採用二級快取技術。
注意:在使用二級快取的時候,要設定一下重新整理間隔(cache標籤中有一個flashInterval屬性)來定時重新整理二級快取,這個重新整理間隔根據具體需求來設定,比如設定30分鐘、60分鐘等,單位為毫秒。
(2)侷限性:
Mybatis二級快取對細粒度的資料,快取實現不好。
場景:對商品資訊進行快取,由於商品資訊查詢訪問量大,但是要求使用者每次查詢都是最新的商品資訊,此時如果使用二級快取,就無法實現當一個商品發生變化只重新整理該商品的快取資訊而不重新整理其他商品快取資訊,因為二級快取是mapper級別的,當一個商品的資訊傳送更新,所有的商品資訊快取資料都會清空。
解決此類問題,需要在業務層根據需要對資料有針對性的快取。
比如可以對經常變化的 資料操作單獨放到另一個namespace的mapper中
相關文章
- Mybatis延遲載入、快取MyBatis快取
- mybatis基礎系列(四)——關聯查詢、延遲載入、一級快取與二級快取MyBatis快取
- Mybatis【20】-- Mybatis延遲載入怎麼處理?MyBatis
- 前端效能優化——延遲載入和非同步載入前端優化非同步
- Mybatis延遲查詢MyBatis
- 影像延遲載入 && 列表圖順序載入
- Mybatis09_一對一、一對多、多對多、延遲載入MyBatis
- VIM Lazy Load 懶載入/延遲載入技術
- Java後端--32--Mybatis的多級快取和懶載入Java後端MyBatis快取
- 精盡MyBatis原始碼分析 - SQL執行過程(四)之延遲載入MyBatis原始碼SQL
- EF中延遲載入的那些事
- Spring Boot 2.2 中的延遲載入Spring Boot
- js延遲載入的方式有哪些?JS
- 延遲載入的一些知識和誤區
- [譯] 延遲載入 React Components (用 react.lazy 和 suspense)React
- JavaScript 中的延遲載入屬性模式JavaScript模式
- Mybatis的快取——一級快取和原始碼分析MyBatis快取原始碼
- MyBatis 快取MyBatis快取
- mybatis快取-二級快取MyBatis快取
- MyBatis加強(1)~myBatis物件關係對映(多對一關係、一對多關係)、延遲/懶載入MyBatis物件
- [譯] 網速敏感的視訊延遲載入方案
- 啟動優化之動態庫延遲載入優化
- SAP Spartacus 的延遲載入 Lazy load 設計原理
- 預載入與快取快取
- 使用JPA和Hibernate延遲載入實體屬性的最佳方法 - Vlad Mihalcea
- Mybatis(三) 快取MyBatis快取
- 05、MyBatis 快取MyBatis快取
- Mybatis的快取MyBatis快取
- 如何建立 Laravel 延遲載入的服務提供者Laravel
- 關於js延遲載入(非同步操作)的方式JS非同步
- mybatis原始碼學習:一級快取和二級快取分析MyBatis原始碼快取
- MyBatis快取機制(一級快取,二級快取)MyBatis快取
- 實現簡單延遲佇列和分散式延遲佇列佇列分散式
- spring和mybatis中的連線池和快取SpringMyBatis快取
- Mybatis快取詳解MyBatis快取
- MyBatis的快取玩法MyBatis快取
- Mybatis快取機制MyBatis快取
- Mybatis 整合 ehcache快取MyBatis快取