日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java ssm框架 缓存_SSM框架之MyBatis3专题4:查询缓存

發布時間:2025/3/11 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java ssm框架 缓存_SSM框架之MyBatis3专题4:查询缓存 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

查詢緩存的使用,主要是為了提高查詢訪問速度。將用戶對同一數據的重復查詢過程簡化,不再每次均從數據庫中查詢獲取結果數據,從而提高訪問速度。

MyBatis的查詢緩存機制,根據緩存區的作用域(聲明周期)可劃分為兩種:一級查詢緩存和二級查詢緩存。

1 一級查詢緩存

MyBatis一級查詢緩存是基于org.apache.ibatis.cache.impl.PerpetualCache類的HashMap本地緩存,其作用域是SqlSession。在同一個SqlSession中兩次執行相同的sql查詢語句,第一次執行完畢后,會將查詢結果寫入到緩存中,第二次會從緩存中直接獲取數據,而不再到數據庫中進行查詢,從而提高查詢效率。

當一個SqlSession結束后,該SqlSession中的一級緩存也就不存在了。MyBatis默認一級查詢緩存是開啟狀態的,且不能夠關閉。

一級緩存執行原理示意圖:

一級緩存執行流程圖:

1.1 一級查詢緩存的存在性證明

1.1.1 修改測試類:

// 證明一級緩存是存在的

@Test

public void test01() {

Student student = dao.selectById(3);

System.out.println(student);

Student student2 = dao.selectById(3);

System.out.println(student2);

}

1.1.2 查看控制臺:

執行完畢后,發現只是執行了一次從DB中的查詢,第二次的結果是直接輸出的。說明,第二次是從SqlSession緩存中讀取的。

1.2 從緩存讀取數據的依據是Sql的id

一級緩存緩存的是相同的Sql映射id的查詢結果,而非相同Sql語句的查詢結果。因為myBatis內部對于查詢緩存,無論是以及一級緩存還是二級查詢緩存,其底層均是使用一個HashMap實現的:key為Sql的id相關內容,value為從數據庫中查詢出的結果。

1.2.1 修改映射文件

在映射文件中對于某一個標簽進行完全復制,然后修改一下這個SQL映射的id。也就是說,這兩個SQL映射除了id不同,其他均相同,即查詢結果肯定是相同的。

select * from t_student where id=#{jjj}

select * from t_student where id=#{jjj}

1.2.2 修改Dao接口

Student selectById(int id);

Student selectById2(int id);

1.2.3 修改測試類

@Test

public void test02() {

Student student = dao.selectById(3);

System.out.println(student);

Student student2 = dao.selectById2(3);

System.out.println(student2);

}

1.2.4 查看控制臺

查看控制臺,發現第二次查詢結果與第一次的完全相同,但是第二次查詢并沒有從緩存中讀取數據,而是直接從DB中進行的查詢。這是因為從緩存讀取數據的依據是查詢SQL的映射id,而非查詢結果。

1.3 增刪改對一級查詢緩存的影響

1.3.1 修改測試類

增、刪、改操作,無論是否進行提交sqlSession.commit(),均會清空一級查詢緩存,使得查詢再次從DB中select。

@Test

public void test03() {

Student student = dao.selectById(3);

System.out.println(student);

dao.deleteById(4);

Student student2 = dao.selectById(3);

System.out.println(student2);

}

1.3.2 查看控制臺

2 內置二級緩存查詢

MyBatis查詢緩存的作用域是根據映射文件mapper的namespace劃分的,相同的namespace的mapper查詢數據存放在同一個緩存區域中。不同的namespace中的數據互不干擾。無論是一級緩存還是二級緩存,都是按照namespace進行分別存放的。

但一級、二級緩存的不同之處在于,SqlSession一旦關閉,則SqlSession中的數據將不存在,即一級緩存就不復存在。而二級緩存的生命周期會與整個應用同步,與SqlSession是否關閉無關。

使用二級緩存的目的,不是共享查詢,因為MyBatis從緩存中讀取數據的依據是SQL的id,而非查詢出的對象。所以,二級緩存中的數據不是為了在多個查詢之間共享(所有查詢中只要查詢結果中存在該對象,就直接從緩存中讀取,這是對數據的共享,Hibernate中的緩存就是為了共享,但是MyBatis的不是。),而是為了延長該查詢結果的保存時間,提高系統性能。

MyBatis內置的二級緩存為:org.apache.ibatis.cache.impl.PerpetualCache。

2.1 二級緩存用法

二級查詢緩存的使用很簡單,只需要完成兩步即可:

2.1.1 實體序列化

要求查詢結果所涉及到的實體類要實現Java.io.Serializable接口。若該實體類存在父類,或者其具有域屬性,則父類與域屬性也要實現序列化接口。

public class Student implements Serializable{

private static final long serialVersionUID = -6979637229268429997L;

private Integer id;

private String name;

private int age;

private double score;

}

2.1.2 mapper映射中添加標簽

在mapper映射文件的標簽中添加子標簽。

2.1.3 二級緩存的配置

為標簽添加一些相關屬性設置,可以對二級緩存的運行性能進行控制。當然,若不指定設置,則均保持默認值。

readOnly="true" size="512"/>

1、eviction:逐出策略。當二級緩存中的對象達到最大值時,就需要通過逐出策略將緩存中的對象溢出緩存。默認為LRU。常用的策略有:

FIFO:First In First Out,先進先出;

LRU:Least Recently Used,未被使用時時間最長;

2、flushInterval:刷新緩存的時間間隔,單位毫秒。這里的刷新緩存即清空緩存。一般不指定,即當執行增刪改時刷新緩存;

3、readOnly:設置緩存中的數據是否為只讀,只讀的緩存會給所有調用者返回緩存對象的相同實例,因此這些對象是不能夠被修改的,這提供了很重要的性能優勢。但是讀寫的緩存會返回緩存對象的拷貝。這會慢一些,但是很安全,因此默認值為false。

4、size:二級緩存中可以存放的最多對象個數。默認為1024個;

2.2 二級查詢緩存的存在性證明

對于映射文件中的同一個查詢,肯定是同一個namespace中的查詢(因為就是同一個查詢)。在一次查詢后,將SqlSession關閉,再進行一次相同查詢,發現并沒有到DB中進行select查詢,說明二級查詢緩存是存在的。

2.2.1 修改測試類

@Test

public void test04() {

sqlSession = MyBatisUtils.getSqlSession();

dao = sqlSession.getMapper(IStudentDao.class);

//第一次查詢

Student student = dao.selectById(3);;

System.out.println(student);

//關閉SqlSession

sqlSession.close();

sqlSession = MyBatisUtils.getSqlSession();

dao = sqlSession.getMapper(IStudentDao.class);

//第二次查詢

Student student2 = dao.selectById(3);

System.out.println(student2);

}

2.2.2 查看控制臺

Cache Hit Ratio表示緩存命中率。開啟二級緩存后,每次執行一次查詢,系統都會計算一次二級緩存的命中率。第一次查詢也是先從緩存中查詢,只不過緩存中一定是沒有的。所以會再從DB中查詢。由于二級緩存中不存在該數據,所以命中率為0。但是第二次查詢是從二級緩存中讀取的,所以這一次的命中率為1/2 = 0.5。當然,若有第三次查詢的話,則命中率會為1/3=0.66。

2.3 增刪改對二級查詢緩存的影響

2.3.1 默認對緩存的刷新

增刪改操作,無論是否進行提交sqlSession.commit(),均會清空一級、二級查詢緩存,使得查詢再次從DB中select。

1、修改測試類:

@Test

public void test05() {

sqlSession = MyBatisUtils.getSqlSession();

dao = sqlSession.getMapper(IStudentDao.class);

//第一次查詢

Student student = dao.selectById(3);;

System.out.println(student);

//關閉SqlSession

sqlSession.close();

sqlSession = MyBatisUtils.getSqlSession();

dao = sqlSession.getMapper(IStudentDao.class);

//刪除一個對象

dao.deleteById(4);

//第二次查詢

Student student2 = dao.selectById(3);

System.out.println(student2);

}

2、查看控制臺:

注意,在第二次查詢時的緩存命中率為0.5,但還是從DB中查詢了。這說明在緩存中與該查詢相對應的key是存在的,但是其value被清空。而value被清空的原因是前面執行了對象DB的增刪改操作,所以不會從緩存中直接將null值返回,而是從DB中進行查詢。

2.3.2 設置增刪改操作不刷新二級緩存

若要使得某個增刪改操作不清空二級緩存,則需要在其或者或者中添加屬性flushCache="false",默認值為true。

delete from t_student where id = #{xxx}

2.4 二級緩存的關閉

二級緩存默認為開啟狀態。若要將其關閉,則需要進行相關配置。

根據關閉的范圍大小,可以分為全局關閉和局部關閉。

2.4.1 全局關閉

所謂全局關閉是指,整個應用的二級緩存全部關閉,所以查詢均不使用二級緩存。全局開關設置在主配置文件的全局設置中,該屬性為cacheEnabled,設置為false,則關閉;設置為true,則開啟,默認值為true。即,二級緩存默認是開啟的。

2.4.2 局部關閉

所謂局部關閉是指,整個應用的二級緩存是開啟的,但是只是對于某個查詢,不使用二級緩存。此時可以單獨只關閉該標簽的二級緩存。

在該要關閉的二級緩存的標簽中,將其屬性useCache設置為false,即可關閉該查詢的二級緩存。該屬性默認為true,即每個查詢的二級緩存默認是開啟的。

select * from t_student where id=#{jjj}

2.5 二級緩存的使用原則

2.5.1 只能夠在一個命名空間下使用二級緩存

由于二級緩存中的數據時基于namespace的,即不同的namespace中的數據互不干擾。在多個namespace中若均存在對同一個表的操作,那么這多個namespace中的數據可能就會出現不一致現象。

2.5.2 在單表上使用二級緩存

如果一個表與其他表有關聯關系,那么就非常有可能存在多個namespace對同一數據的操作。而不同的namespace中的數據互不干擾,所以有可能出現這多個namespace中的數據不一致現象。

2.5.3 查詢多于修改時使用二級緩存

在查詢操作遠遠多于增刪改操作的情況下可以使用二級緩存。因為任何增刪改操作都將刷新二級緩存,對二級緩存的頻繁刷新就會降低系統性能。

3 ehcache二級查詢緩存

mybatis的特長是SQL操作,緩存數據管理不是其特長,為了提高緩存的性能,myBatis允許使用第三方緩存產品。ehCache就是其中一種。

注意,使用ehcache二級緩存,實體類無需實現序列化接口。

3.1 導入Jar包

這里需要兩個Jar包:一個為ehcache的核心Jar包,一個是myBatis與ehcache整合的插件Jar包。它們可以從https://github.com/mybatis/ehcache-cache/releases 下面。

解壓該文件,獲取到它們。其中lib下的是ehcache的核心Jar包。

3.2 ehcache.xml

解壓EHCache的核心Jar包ehcache-core-2.6.8.jar,將其中的一個配置文件ehcache.failsafe.xml直接放到項目的src目錄下,并更名為ehcache.xml。

3.2.1 < diskStore/>標簽

指定一個文件目錄,當內存空間不夠,需要將二級緩存中的數據寫到硬盤上時,會寫到這個指定目錄中。其值一般為java.io.tmpdir,表示當前系統的默認文件臨時目錄。

當前系統的默認文件臨時目錄,可以通過System.property()方法查看:

@Test

public void test() {

String path = System.getProperty("java.io.tempdir");

System.out.println(path);

}

3.2.2 < defaultCache/>標簽

maxElementsInMemory="10000"

eternal="false"

timeToIdleSeconds="120"

timeToLiveSeconds="120"

maxElementsOnDisk="10000000"

diskExpiryThreadIntervalSeconds="120"

memoryStoreEvictionPolicy="LRU">

設定緩存的默認屬性數據:

1、maxElementsInMemory:指定該內存緩存可以存放緩存對象的最多個數;

2、eternal:設定緩存對象是否不會過期。若設為true,表示對象永遠不會過期,此時會忽略timeToIdleSeconds與timeToLiveSeconds屬性。默認值為false;

3、timeToldleSeconds:設定允許對象處于空閑狀態的最長時間,以秒為單位。當對象自從最近一次被訪問后,若處于空閑狀態的時間超過了timeToldleSeconds設定的值,這個對象就會過期。當對象過期,ehcache就會將它從緩存中清除。設置值為0,則對象可以無限期地處于空閑狀態。

4、timeToLiveSeconds:設定對象允許存在于緩存中的最長時間,以秒為單位。當對象自從被存放到緩存后,若處于緩存中的時間超過了timeToLiveSeconds設定的值,這個對象就會過期。當對象過期,ehcache就會將它從緩存中清除。設置值為0,則對象可以無限期地存在于緩存中。注意,只有timeToLiveSeconds>=timeToldleSeconds時,才有意義;

5、overflowToDisk:設定為true,表示當緩存對象達到maxElementsInMemory界限時,會將溢出的對象寫到元素指定的硬盤目錄緩存中;

6、maxElementsOnDisk:指定硬盤緩存區可以存放緩存對象的最多個數;

7、diskPersistent:指定當程序結束時,硬盤緩存區中的緩存對象是否做持久化;

8、diskExpiryThreadIntervalSeconds:指定硬盤中緩存對象的失效時間間隔;

9、memoryStoreEvictionPolicy:如果內存緩存區超過限制,選擇移向硬盤緩存區中的對象時使用的策略。支持三種策略:

FIFO:First In First Out,先進先出;

LFU:Less Frequenlty Used,最少使用;

LRU,Least Recently Used,最近最少使用;

3.3 啟用ehcache緩存機制

在映射文件的mapper中的中通過type指定緩存機制為ehcache緩存。默認為myBatis內置的二級緩存org.apache.ibatis.cache.impl.PerpetualCache。

該類在mybatis-ehcache的jar包中可以找到。

3.4 ehcache在不同mapper中的個性化設置

在ehcache.xml中設置的屬性值,會對該項目中所有使用ehcache緩存機制的緩存區域起作用。一個項目中可以有多個mapper,不同的mapper有不同的緩存區域。對于不同緩存區域也可進行專門針對于當前區域的個性化設置,可通過指定不同mapper的屬性值來設置。

屬性值的優先級高于ehcache.xml中的屬性值。

總結

以上是生活随笔為你收集整理的java ssm框架 缓存_SSM框架之MyBatis3专题4:查询缓存的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。