Java|mybatis的一级缓存和二级缓存

一级缓存 1、说明 mybatis默认开启一级缓存,一级缓存的作用域是SqlSession范围的,当在同一个sqlSession中执行两次相同的sql语句时,第一次执行完毕会将数据库中查询的数据写到缓存,第二次查询时会从缓存中获取数据,不再去底层数据库查询,从而提高查询效率。
在分布式的环境中,mybatis的一二级缓存非常危险,二级缓存一定要关闭,一级缓存视情况关闭
Java|mybatis的一级缓存和二级缓存
文章图片

一级缓存失效的四种情况:

  1. sqlSession不同。
  2. sqlSession相同,查询条件不同。因为缓存条件不同,缓存中还没有数据。
  3. sqlSession相同,在两次相同查询条件中间执行过增删改操作。(因为中间的增删改可能对缓存中数据进行修改,所以不能用)
  4. sqlSession相同,手动清空了一级缓存。
2、关闭方法 (1)注解形式
使用注解 @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
mapperselect 标签中设置 statementType=STATEMENT
statementType的设置有3种:
  1. STATEMENT:直接操作sql,不进行预编译,获取数据
  2. PREPARED:(默认)预处理,参数,进行预编译,获取数据
  3. CALLABLE:执行存储过程————CallableStatement
(4)设置 flushCache
mapperselect 标签中设置 flushCache=“true”
(5)设置 localCacheScope
全局设置 localCacheScope=STATEMENT
参考:https://blog.csdn.net/u011649691/article/details/116058056
2、案例 我们在 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的一级缓存和二级缓存】工作机制:
  1. 一个会话,查询一条数据,这个数据会被放在当前会话的一级缓存中。
  2. 如果会话被关闭了,一级缓存中的数据会被保存到二级缓存。新的会话查询信息就会参照二级缓存。
  3. 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

    推荐阅读