MyBatis二级缓存
一级缓存默认开启,缓存范围是SqlSession会话,二级缓存需手动开启,缓存范围是Mapper Namespace。在某个namespace中手动开启的二级缓存被所有SqlSession共享。二级缓存开启后默认所有查询操作均使用缓存,为保证数据的一致性,写操作commit提交时对该namespace缓存强制清空。
配置useCache=false可以不用缓存
配置flushCache=true代表强制清空缓存
<select id="selectById" parameterType="Integer" resultType="com.MyBatis.entity.Goods">
select * from t_goods where goods_id = #{value}
</select>
验证一级缓存:
在同一个SqlSession对象中,执行两次相同的查询操作
@Test
public void testlv1Cache(){
SqlSession sqlSession=null;
try{
sqlSession=MyBatisUtils.openSession();
Goods goods = sqlSession.selectOne("goods.selectById",1603);
Goods goods1 = sqlSession.selectOne("goods.selectById",1603);
System.out.println(goods.hashCode()+":"+goods1.hashCode());
}catch (Exception e){
if(sqlSession!=null){
sqlSession.rollback();
}
throw e;
}finally {
MyBatisUtils.closeSession(sqlSession);
}
}
如下图,goods和goods1指向同一个对象
在两个SqlSession对象中执行重复查询
@Test
public void testlv1Cache(){
SqlSession sqlSession=null;
try{
sqlSession=MyBatisUtils.openSession();
Goods goods = sqlSession.selectOne("goods.selectById",1603);
Goods goods1 = sqlSession.selectOne("goods.selectById",1603);
System.out.println(goods.hashCode()+":"+goods1.hashCode());
}catch (Exception e){
if(sqlSession!=null){
sqlSession.rollback();
}
throw e;
}finally {
MyBatisUtils.closeSession(sqlSession);
}
try{
sqlSession=MyBatisUtils.openSession();
Goods goods = sqlSession.selectOne("goods.selectById",1603);
Goods goods1 = sqlSession.selectOne("goods.selectById",1603);
System.out.println(goods.hashCode()+":"+goods1.hashCode());
}catch (Exception e){
if(sqlSession!=null){
sqlSession.rollback();
}
throw e;
}finally {
MyBatisUtils.closeSession(sqlSession);
}
}
一级缓存的范围只在SqlSession对象中
二级缓存的开启
在mapper下增加cache标签
<?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="goods">
<!--开启了二级缓存-->
<cache eviction="LRU" flushInterval="600000" size="512" readOnly="true"/>
<select id="selectById" parameterType="Integer" resultType="com.MyBatis.entity.Goods">
select * from t_goods where goods_id = #{value}
</select>
</mapper>
测试代码:
@Test
public void testlv2Cache(){
SqlSession sqlSession=null;
try{
sqlSession=MyBatisUtils.openSession();
Goods goods = sqlSession.selectOne("goods.selectById",1603);
System.out.println(goods.hashCode());
}catch (Exception e){
if(sqlSession!=null){
sqlSession.rollback();
}
throw e;
}finally {
MyBatisUtils.closeSession(sqlSession);
}
try{
sqlSession=MyBatisUtils.openSession();
Goods goods = sqlSession.selectOne("goods.selectById",1603);
System.out.println(goods.hashCode());
}catch (Exception e){
if(sqlSession!=null){
sqlSession.rollback();
}
throw e;
}finally {
MyBatisUtils.closeSession(sqlSession);
}
}
cache的四个设置项:
1.eviction是缓存的清楚策略,当缓存对象数量达到上限后,自动触发对应算法对缓存对象清除
1.LRU - 最近最久未使用:已出最长时间不被使用的对象。
O1 O2 O3 O4 .. O512
14 99 83 1 893
2.FIFO - 先进先出:按对象进入缓存的顺序移除
3.SOFT - 软引用:移除基于垃圾收集器状态和软引用规则的对象
4.WEAK - 弱引用:更积极的移除基于垃圾收集器状态和弱引用规则的对象
2.flushInterval 代表间隔多长时间自动清空缓存,单位毫秒 600000ms=10min
3.size 缓存储存上限,用于保存对象或集合(一个集合算一个对象)的数量上限
4.readOnly 设置为true,代表返回只读缓存,每次从缓存取出的是缓存对象本身,执行效率更高
设置为false,代表每次取出的是缓存 ‘副本’ ,每一次取出的对象是不同的,安全性较高
List在放入缓存时会被当做一个对象,对内存的使用非常大,因此可以在<select>标签中添加属性 useCache="false" 表示不被缓存。在<select>标签中添加属性flushCache="true" 表示在sql执行后强制清空缓存
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!