一级缓存
1、说明 mybatis默认开启一级缓存,一级缓存的作用域是SqlSession
范围的,当在同一个sqlSession
中执行两次相同的sql语句时,第一次执行完毕会将数据库中查询的数据写到缓存,第二次查询时会从缓存中获取数据,不再去底层数据库查询,从而提高查询效率。
在分布式的环境中,mybatis的一二级缓存非常危险,二级缓存一定要关闭,一级缓存视情况关闭
文章图片
一级缓存失效的四种情况:
- sqlSession不同。
- sqlSession相同,查询条件不同。因为缓存条件不同,缓存中还没有数据。
- sqlSession相同,在两次相同查询条件中间执行过增删改操作。(因为中间的增删改可能对缓存中数据进行修改,所以不能用)
- sqlSession相同,手动清空了一级缓存。
使用注解
@Options(flushCache = Options.FlushCachePolicy.TRUE)
可指定仅仅某个Mapper关闭注解)@Options(flushCache = Options.FlushCachePolicy.TRUE)
@Select("select * from ge_jdbc_datasource where id = #{id,jdbcType=BIGINT} and status = 1")
@ResultMap("resultMap")
JdbcDataSource find(Long id);
(2)传入随机数
比如sql传参random()数值 或者 sql传入当前时间毫秒数,切记一定要从方法形参传过去而不要在sql中拼写,否则无效
举例说明:下面方式无效
select id from ge_jdbc_datasource where id = 1 and STATUS = 1 AND NOW()=NOW()
(3)设置 statementType
在
mapper
的 select
标签中设置 statementType=STATEMENT
statementType
的设置有3种:STATEMENT
:直接操作sql,不进行预编译,获取数据PREPARED
:(默认)预处理,参数,进行预编译,获取数据CALLABLE
:执行存储过程————CallableStatement
在
mapper
的 select
标签中设置 flushCache=“true”
(5)设置 localCacheScope
全局设置
localCacheScope=STATEMENT
参考:https://blog.csdn.net/u011649691/article/details/1160580562、案例 我们在
getPaymentById
方法中写了两次查询,并且保证方法内的 sqlSession
是同一个。在两次查询期间对数据进行修改,将 serial=001
修改为 serial=002
。package com.scy.springcloud.service.impl;
import com.scy.springcloud.dao.PaymentDao;
import com.scy.springcloud.entities.Payment;
import com.scy.springcloud.service.PaymentService;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
@Service
public class PaymentServiceImpl implements PaymentService {
@Resource
private PaymentDao paymentDao;
//这里注入的sqlSession是org.mybatis.spring.SqlSessionTemplate
/*@Resource
public SqlSession sqlSession;
*/@Resource
SqlSessionFactory sqlSessionFactory;
@Override
public Payment getPaymentById2(Long id) {
//org.apache.ibatis.session.defaults.DefaultSqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
Payment payment = sqlSession.selectOne("getPaymentById", id);
System.out.println(payment.toString());
try {
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Payment payment2 = sqlSession.selectOne("getPaymentById", id);
System.out.println(payment2.toString());
sqlSession.close();
return payment2;
}
}
查询1(开启缓存)
两次查询是同样的,没有改变,说明开启了一级缓存。
Payment(id=31, serial=001)
Payment(id=31, serial=001)
查询2(关闭缓存)
在
select
标签中加入 flushCache="true"
后,使一级缓存失效。id="getPaymentById" parameterType="Long" resultMap="BaseResultMap" flushCache="true">
select * from payment where id = #{id};
第二次查询结果变为serial=002,说明一级缓存失效。
Payment(id=31, serial=001)
Payment(id=31, serial=002)
二级缓存 1、说明
MyBatis
的二级缓存是Application级别的缓存,二级缓存的作用域默认为mapper(namespace)
【Java|mybatis的一级缓存和二级缓存】工作机制:
- 一个会话,查询一条数据,这个数据会被放在当前会话的一级缓存中。
- 如果会话被关闭了,一级缓存中的数据会被保存到二级缓存。新的会话查询信息就会参照二级缓存。
- sqlSession > Employee>employee
sqlSession >DepartmentMapper=>Department
不同的namespace查出的数据会放在自己对应的缓存中。
查出的数据首先放在一级缓存中,只有一级缓存被关闭或者提交以后,一级缓存数据才会转移到二级缓存
2、开启方法 (1)方式一
在
mybatis
的配置文件中进行配置
>name="cacheEnabled" value="https://www.it610.com/article/true"/>
(2)方式二
在
application.yml
文件中进行配置开启mybatis的二级缓存 mybatis.configuration.cache-enabled=true
# 开启二级缓存
mybatis:
configuration:
cache-enabled: true# 开启sql打印(可以方便查看是否使用了缓存)
logging:
level:
com.scy.springcloud.dao: debug
3、开启缓存配置 开启二级缓存的分开关。
要加入cache的配置二级缓存才会开启。
cache 相关属性:
-
eviction
: 缓存的回收策略
LRU
(默认):最近最少使用,移除最长时间不被使用的对象FIFO
:先进先出,安对象进入缓存的顺序来移除它们SOFT
:软引用,移除基于垃圾回收器的状态和软引用规则的对象WEAK
: 弱引用,更积极的移除基于垃圾收集器状态和弱引用规则的对象
-
flushInterval
:缓存刷新间隔 缓存多长时间清空一次,默认不清空,设置一个毫秒值
-
readOnly
:是否只读 。
true
:只读,mybatis
认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。mybatis
为了加快获取速度,直接会将数据在缓存中的引用交给用户,不安全,但速度快。false
:非只读,mybatis
觉得获取的数据可能会被修改。会利用序列化&反序列化的技术克隆一份新的数据给你,安全,但速度慢。
-
size
:缓存最多存放多少个引用。默认1024。
-
type
:指定自定义缓存的全类名,实现Mybatis
提供的Cache
接口即可。
实体对象要
implements Serializable
,否则报错public class User implements Serializable{
}
启动工程,如果出现
Cache Hit Ratio . # 表示缓存开启了.....
参考:
Mybatis二级缓存失效及二级缓存使用简介
https://blog.csdn.net/sao_jie/article/details/119297811
浅谈一下mybatis中@CacheNamespace和@CacheNamespaceRef的区别以及使用
https://blog.csdn.net/lovely960823/article/details/111277801
推荐阅读
- mybatis|mybatis一级缓存和二级缓存原理
- 缓存|MyBatis一级缓存和二级缓存
- Java集合知识点总结和重点源码分析
- 数据库|Mysql高级篇
- 同事写了一个责任链模式,bug 无数...
- java实战开发|阿里巴巴《Java开发手册(黄山版)》阅读笔记
- 剑指offer|剑指 Offer II 049. 从根节点到叶节点的路径数字之和
- 大数据|计算机科学领域 直接 间接_为什么计算机科学领域的女性很少()
- 软件测试|接口测试项目(非常值得练手)