二級緩存
MyBatis 的二級緩存非常強(qiáng)大屎慢,它不同于一級緩存只存在于 SqlSession 的生命周期中,而是可以理解為存在于 SqlSessionFactory 的生命周期中淹接。
配置二級緩存
MyBatis 的二級緩存是和命名空間綁定的鲸鹦,即二級緩存需要配置在 Mapper.xml 映射文件中憋沿,或者配置在 Mapper.java 接口中。在映射文件中季稳,命名空間就是 XML 根節(jié)點 mapper 的 namespace 屬性擅这。在 Mapper 接口中,命名空間就是接口的全限定名稱景鼠。
開啟二級緩存
在 MyBatis 的全局配置 settings 中有一個參數(shù) cacheEnabled
仲翎,這個參數(shù)是二級緩存的全局開關(guān),默認(rèn)值是 true
铛漓,初始狀態(tài)為啟用狀態(tài)溯香。如果把這個參數(shù)設(shè)置為 false
,即使有后面的二級緩存配置浓恶,也不會生效逐哈。由于這個參數(shù)值默認(rèn)為 true
,所以不必配置问顷,如果想配置,可以在 mybatis-config.xml 中添加如下代碼禀梳。
<settings>
<!--開啟二級緩存-->
<setting name="cacheEnabled" value="true"/>
</settings>
Mapper.xml 中配置二級緩存
在保證二級緩存的全局配置開啟的情況下杜窄,給 UserMapper.xml 開啟二級緩存只需要在 UserMapper.xml 中添加 <cache/>
標(biāo)簽即可,添加后的 UserMapper.xml 如下算途。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mybatis.mapper.UserMapper">
<!--二級緩存默認(rèn)配置-->
<cache/>
<!--其他配置-->
</mapper>
默認(rèn)的二級緩存會有如下效果塞耕。
- 映射語句文件中的所有 SELECT 語句將會配緩存。
- 映射語句文件中的所有 INSERT嘴瓤、UPDATE扫外、DELETE 語句會刷新緩存。
- 緩存會使用 Least Recently Used (LRU廓脆,最近最少使用的)算法來回收筛谚。
- 根據(jù)時間表(如 no Flush Interval,沒有刷新時間)停忿,緩存不會以任何時間順序來刷新驾讲。
- 緩存會存儲集合或?qū)ο螅o論查詢方法返回什么類型的值)的1024個引用。
- 緩存會被視為 read/write(可讀/可寫)的席赂,意味著對象檢索不是共享的吮铭,而且可以安全的被調(diào)用者修改,而不干擾其他調(diào)用者或線程所做的潛在修改颅停。
所有的這些屬性都可以通過緩存原屬的屬性來修改谓晌,示例如下。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mybatis.mapper.UserMapper">
<!--二級緩存自定義配置-->
<cache eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
<!--其他配置-->
</mapper>
這個更高級的配置創(chuàng)建了一個 FIFO 緩存癞揉,并每隔60秒刷新一次纸肉,存儲集合或?qū)ο蟮?12個引用溺欧,而且返回的對象被認(rèn)為是只讀的,因此在不同的線程中的調(diào)用者之間修改它們會導(dǎo)致沖突毁靶。
<cache>
標(biāo)簽可以配置的屬性如下胧奔。
-
eviction(回收策略)
- LUR(最近最少使用):移除最長時間不被使用的對象,這是默認(rèn)值预吆。
- FIFO(先進(jìn)先出):按對象進(jìn)入緩存的順序來析出它們龙填。
- SOFT(軟引用):移除基于垃圾回收器狀態(tài)和軟引用規(guī)則的對象。
- WEAK(弱引用):更積極的移除基于垃圾收集器狀態(tài)和弱引用規(guī)則的對象拐叉。
-
flushInterval(刷新時間)
可以被設(shè)置為任意的正整數(shù)岩遗,而且她們代表一個合理的毫秒形成的時間段。默認(rèn)情況不設(shè)置凤瘦,即沒有刷新間隔宿礁,緩存僅僅在調(diào)用語句時刷新。
-
size(引用數(shù)目)
可以被設(shè)置為任意的正整數(shù)蔬芥,要記住緩存的對象數(shù)目和運(yùn)行環(huán)境的可用內(nèi)存資源數(shù)目梆靖。默認(rèn)值是 1024。
-
readOnly(只讀)
readOnly 屬性可以配設(shè)置為 true 或 false笔诵。只讀的緩存會給所有調(diào)用者返回緩存對象的相同實例返吻,因此這些對象不能被修改,這提供了很重要的性能優(yōu)勢乎婿〔饨可讀寫的緩存會通過序列化返回緩存對象的拷貝,這種方式會慢一些谢翎,但是安全捍靠,因此默認(rèn)是 false。
Mapper 接口中配置二級緩存
在使用注解方式進(jìn)行開發(fā)時森逮,如果相對注解方法啟用二級緩存榨婆,則需要在 Mapper 接口中進(jìn)行配置。
@CacheNamespace
public interface AnnotationUserMapper {
// 接口方法
}
只需要在接口類上增加 @CacheNamespace
注解即可 褒侧,該注解同 XML 文件中的 <cache/>
標(biāo)簽纲辽。
自定義配置各項屬性,示例如下璃搜。
@CacheNamespace(
eviction = FifoCache.class,
flushInterval = 60000,
size = 512,
readWrite = true
)
這里的 readWrite
屬性和 XML 中的 readOnly
屬性一樣拖吼,用于配置緩存是否為只讀類型,在這里 true 為讀寫这吻,false為只讀吊档,默認(rèn)為 true。
xml 和 接口中同時配置二級緩存
當(dāng)同時使用注解方式和 XML 映射文件時唾糯,如果同時配置了二級緩存怠硼,就會拋出如下異常鬼贱。
Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.lang.IllegalArgumentException: Caches collection already contains value for com.mybatis.mapper.AnnotationUserMapper
這是應(yīng)為 Mapper 接口和對應(yīng)的 XML 文件是相同的命名空間,想使用二級緩存香璃,兩者必須同時配置这难,如果接口中不存在使用注解的方法,則可以只在 XML 文件中配置葡秒。
因此這個時候應(yīng)該使用參照緩存來避免同時配置二級緩存導(dǎo)致的錯誤姻乓。
1.在 Mapper 接口中進(jìn)行修改
@CacheNamespaceRef(AnnotationUserMapper.class)
public interface AnnotationUserMapper {
// 接口方法
}
如例所示,想讓 AnnotationUserMapper
接口中的注釋方法和 XML 中的方法使用相同緩存眯牧,因此使用參照緩存 AnnotationUserMapper.class
蹋岩,這樣就會使用命名空間為 com.mybatis.mapper.AnnotationUserMapper
的緩存配置,即 AnnotationUserMapper.xml
中配置的緩存学少。
2.在 XML 映射文件中修改
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mybatis.mapper.AnnotationUserMapper">
<cache-ref namespace="com.mybatis.mapper.AnnotationUserMapper"/>
</mapper>
這樣配置后剪个,XML 就會引用 Mapper 接口中配置的二級緩存。
參考資料:MyBatis 從入門到精通 作者:劉增輝