首页 > 其他分享 >Mybatis15 - 二级缓存

Mybatis15 - 二级缓存

时间:2023-02-14 19:33:55浏览次数:44  
标签:缓存 SqlSession 查询 Employee 二级缓存 Mybatis15 EmployeeMapper

二级缓存(手动开启)

这里我们使用的是Mybatis自带的二级缓存,也可以称之为是内置的。

二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取

二级缓存开启的条件

  • 在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
  • 在映射文件中设置标签 <cache/>
  • 二级缓存必须在SqlSession关闭或提交之后有效,一级缓存数据在此时保存到二级缓存中
  • 查询的数据所转换的实体类类型必须实现序列化的接口

二级缓存失效的情况

  • 两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效

1. 代码测试二级缓存

①开启二级缓存功能

在想要使用二级缓存的Mapper配置文件中加入cache标签

<mapper namespace="com.atguigu.mybatis.EmployeeMapper">
    
    <!-- 加入cache标签启用二级缓存功能 -->
    <cache/>
②让实体类支持序列化
public class Employee implements Serializable {
③junit测试

这个功能的测试操作需要将SqlSessionFactory对象设置为成员变量

@Test
public void testSecondLevelCacheExists() {
    SqlSession session = factory.openSession();
    
    EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
    
    Employee employee = mapper.selectEmployeeById(2);
    
    log.debug("employee = " + employee);
    
    // 在执行第二次查询前,关闭当前SqlSession
    session.close();
    
    // 开启一个新的SqlSession
    session = factory.openSession();
    
    mapper = session.getMapper(EmployeeMapper.class);
    
    employee = mapper.selectEmployeeById(2);
    
    log.debug("employee = " + employee);
    
    session.close();
    
}
④缓存命中率

日志中打印的Cache Hit Ratio叫做缓存命中率

缓存命中率=命中缓存的次数/查询的总次数

2. 查询结果存入二级缓存的时机

结论:SqlSession关闭的时候,一级缓存中的内容会被存入二级缓存

// 1.开启两个SqlSession
SqlSession session01 = factory.openSession();
SqlSession session02 = factory.openSession();
    
// 2.获取两个EmployeeMapper
EmployeeMapper employeeMapper01 = session01.getMapper(EmployeeMapper.class);
EmployeeMapper employeeMapper02 = session02.getMapper(EmployeeMapper.class);
    
// 3.使用两个EmployeeMapper做两次查询,返回两个Employee对象
Employee employee01 = employeeMapper01.selectEmployeeById(2);
Employee employee02 = employeeMapper02.selectEmployeeById(2);
    
// 4.比较两个Employee对象
log.debug("employee02.equals(employee01) = " + employee02.equals(employee01));

修改代码:

// 1.开启两个SqlSession
SqlSession session01 = factory.openSession();
SqlSession session02 = factory.openSession();
    
// 2.获取两个EmployeeMapper
EmployeeMapper employeeMapper01 = session01.getMapper(EmployeeMapper.class);
EmployeeMapper employeeMapper02 = session02.getMapper(EmployeeMapper.class);
    
// 3.使用两个EmployeeMapper做两次查询,返回两个Employee对象
Employee employee01 = employeeMapper01.selectEmployeeById(2);
    
// ※第一次查询完成后,把所在的SqlSession关闭,使一级缓存中的数据存入二级缓存
session01.close();
Employee employee02 = employeeMapper02.selectEmployeeById(2);
    
// 4.比较两个Employee对象
log.debug("employee02.equals(employee01) = " + employee02.equals(employee01));
    
// 5.另外一个SqlSession用完正常关闭
session02.close();

二级缓存的相关配置

在mapper配置文件中添加的cache标签可以设置一些属性:

①eviction属性:缓存回收策略,默认的是 LRU。

  • LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。

  • FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。

  • SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。

  • WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

②flushInterval属性:刷新间隔,单位毫秒

  • 默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新

③size属性:引用数目,正整数

  • 代表缓存最多可以存储多少个对象,太大容易导致内存溢出

④readOnly属性:只读, true/false

  • true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了 很重要的性能优势。
  • false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。

MyBatis缓存查询的顺序

先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用。

如果二级缓存没有命中,再查询一级缓存

如果一级缓存也没有命中,则查询数据库

SqlSession关闭之后,一级缓存中的数据会写入二级缓存

标签:缓存,SqlSession,查询,Employee,二级缓存,Mybatis15,EmployeeMapper
From: https://www.cnblogs.com/Ashen-/p/17120671.html

相关文章

  • MyBatis的二级缓存整合redis
    MyBatis自带的二级缓存存在的问题在前面我们使用@CacheNamespace​实现了430.MyBatis的二级缓存,这个底层使用HashMap​来实现。在单机环境下没有问题,但是在分布......
  • MyBatis的二级缓存整合redis
    MyBatis自带的二级缓存存在的问题在前面我们使用@CacheNamespace​实现了430.MyBatis的二级缓存,这个底层使用HashMap​来实现。在单机环境下没有问题,但是在分布......
  • MyBatis的二级缓存整合redis
    MyBatis自带的二级缓存存在的问题在前面我们使用@CacheNamespace​实现了430.MyBatis的二级缓存,这个底层使用HashMap​来实现。在单机环境下没有问题,但是在分布......
  • MyBatis的二级缓存整合redis
    MyBatis自带的二级缓存存在的问题在前面我们使用@CacheNamespace​实现了430.MyBatis的二级缓存,这个底层使用HashMap​来实现。在单机环境下没有问题,但是在分布......
  • MyBatis的二级缓存整合redis
    MyBatis自带的二级缓存存在的问题在前面我们使用@CacheNamespace​实现了430.MyBatis的二级缓存,这个底层使用HashMap​来实现。在单机环境下没有问题,但是在分布......
  • MyBatis的二级缓存整合redis
    MyBatis自带的二级缓存存在的问题在前面我们使用@CacheNamespace​实现了430.MyBatis的二级缓存,这个底层使用HashMap​来实现。在单机环境下没有问题,但是在分布......
  • MyBatis的二级缓存整合redis
    MyBatis自带的二级缓存存在的问题在前面我们使用@CacheNamespace​实现了430.MyBatis的二级缓存,这个底层使用HashMap​来实现。在单机环境下没有问题,但是在分布......
  • MyBatis的二级缓存整合redis
    MyBatis自带的二级缓存存在的问题在前面我们使用@CacheNamespace​实现了430.MyBatis的二级缓存,这个底层使用HashMap​来实现。在单机环境下没有问题,但是在分布......
  • MyBatis的二级缓存整合redis
    MyBatis自带的二级缓存存在的问题在前面我们使用@CacheNamespace​实现了430.MyBatis的二级缓存,这个底层使用HashMap​来实现。在单机环境下没有问题,但是在分布......
  • MyBatis的二级缓存整合redis
    MyBatis自带的二级缓存存在的问题在前面我们使用@CacheNamespace​实现了430.MyBatis的二级缓存,这个底层使用HashMap​来实现。在单机环境下没有问题,但是在分布......