mybatis默认开启一级缓存,一级缓存的作用域是SqlSession
范围的,当在同一个sqlSession
中执行两次相同的sql语句时,第一次执行完毕会将数据库中查询的数据写到缓存,第二次查询时会从缓存中获取数据,不再去底层数据库查询,从而提高查询效率。
在分布式的环境中,mybatis的一二级缓存非常危险,二级缓存一定要关闭,一级缓存视情况关闭
一级缓存失效的四种情况:
使用注解 @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);
比如sql传参random()数值 或者 sql传入当前时间毫秒数,切记一定要从方法形参传过去而不要在sql中拼写,否则无效
举例说明:下面方式无效
select id from ge_jdbc_datasource where id = 1 and STATUS = 1 AND NOW()=NOW()
在mapper
的 select
标签中设置 statementType=STATEMENT
statementType
的设置有3种:
STATEMENT
:直接操作sql,不进行预编译,获取数据PREPARED
:(默认)预处理,参数,进行预编译,获取数据CALLABLE
:执行存储过程————CallableStatement在 mapper
的 select
标签中设置 flushCache=“true”
全局设置 localCacheScope=STATEMENT
参考:https://blog.csdn.net/u011649691/article/details/116058056
我们在 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;
}
}
两次查询是同样的,没有改变,说明开启了一级缓存。
Payment(id=31, serial=001)
Payment(id=31, serial=001)
在 select
标签中加入 flushCache="true"
后,使一级缓存失效。
<select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap" flushCache="true">
select * from payment where id = #{id};
select>
第二次查询结果变为serial=002,说明一级缓存失效。
Payment(id=31, serial=001)
Payment(id=31, serial=002)
MyBatis
的二级缓存是Application级别的缓存,二级缓存的作用域默认为mapper(namespace)
工作机制:
一个会话,查询一条数据,这个数据会被放在当前会话的一级缓存中。
如果会话被关闭了,一级缓存中的数据会被保存到二级缓存。新的会话查询信息就会参照二级缓存。
sqlSession > Employee>employee
sqlSession >DepartmentMapper=>Department
不同的namespace查出的数据会放在自己对应的缓存中。
效果:
查出的数据首先放在一级缓存中,只有一级缓存被关闭或者提交以后,一级缓存数据才会转移到二级缓存
在 mybatis
的配置文件中进行配置
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
settings>
configuration>
在application.yml
文件中进行配置开启mybatis的二级缓存 mybatis.configuration.cache-enabled=true
# 开启二级缓存
mybatis:
configuration:
cache-enabled: true
# 开启sql打印(可以方便查看是否使用了缓存)
logging:
level:
com.scy.springcloud.dao: debug
开启二级缓存的分开关。
要加入cache的配置二级缓存才会开启。
<mapper namespace="com.scy.springcloud.dao.PaymentDao">
<cache eviction="LRU" flushInterval="20000" readOnly="true" size="1024">
cache>
mapper>
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