首页 > 其他分享 >MyBatis(二五):缓存——二级缓存

MyBatis(二五):缓存——二级缓存

时间:2022-09-18 10:00:21浏览次数:71  
标签:缓存 对象 UserMapper SqlSession 二级缓存 移除 MyBatis

上一篇我们学习了一级缓存,这次我们来学习二级缓存。

一、什么是二级缓存

二级缓存也叫全局缓存,是namespace级别的缓存,每一个命名空间对应一个二级缓存。

二、二级缓存的工作机制

1.每个SqlSession对应一个一级缓存。

2.当SqlSession关闭时,对应的一级缓存就会消失,但是如果我们开启了二级缓存,一级缓存的内容就会在会话关闭时存入对应的二级缓存中。

3.此时新的SqlSession会话就可以从二级缓存中获取内容。

三、二级缓存的具体应用

 1.mybatis-config.xml核心文件配置

 <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>

这个配置不是必要的,因为官方文档中说明这个配置是默认开启的。

设置名描述有效值默认值
cacheEnabled 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 true | false true

2.Mapper.xml配置

<cache eviction="FIFO"
            flushInterval="60000"
            size="512"
            readOnly="true"/>

这是官方给出的一个二级缓存的例子,这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。

可用的清除策略有:

  • LRU – 最近最少使用:移除最长时间不被使用的对象。
  • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
  • SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。
  • WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。

默认的清除策略是 LRU。

flushInterval(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。

size(引用数目)属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。

readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。

3.测试

    @Test
    public void getUserById() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUserById(10001);
        System.out.println(user);
        sqlSession.close();
        System.out.println("=========================================");
        SqlSession sqlSession2 = MyBatisUtil.getSqlSession();
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
        User user2 = userMapper2.getUserById(10001);
        System.out.println(user2);
        sqlSession2.close();
    }

测试结果如下:

 

 可以看见第二次查询并没有操作数据库。

 

当然我们也可以直接使用最简单的二级缓存配置:

<cache/>

此时我们去测试,结果报错:

 

 报的错误是User类没有序列化,那么为什么会出现这个问题呢?

因为二级缓存readOnly默认为false,而可读写的缓存会通过序列化返回缓存对象的拷贝,所以,此时需要实体类实现Serializable接口或者在cache/中配置readOnly=true。

我们去实现Serializable接口:

public class User implements Serializable {}

此时再次测试:

 

 没有问题。

 

(本文仅作个人学习记录用,如有纰漏敬请指正)

标签:缓存,对象,UserMapper,SqlSession,二级缓存,移除,MyBatis
From: https://www.cnblogs.com/jmsstudy/p/16703301.html

相关文章

  • 05--Redis高级:持久化、主从复制、哨兵、集群、redis做缓存
    1redis持久化#持久化redis的所有数据保存在内存中,对数据更新将异步的保存到硬盘上#实现方式#1.快照(全量复制):某时某刻数据的一个完整备份-mysql的......
  • MyBatis
    MyBatis持久层开发MyBatis配置文件<?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPEconfigurationPUBLIC"-//mybatis.org//DTDConfig3.0//EN""http://myb......
  • Redis缓存查询(防缓存击穿)
    @GetMapping("getResourceByConsumer")publicAPIResponsegetResourceByConsumer(StringconsumerId){Stringerror="";try{List......
  • MyBatis-Plus插入值后返回主键
    LZ做练手设计的时候有这样一个订单需求,先插入订单表数据(t_order),再写入订单详情表(t_orderDetail),详情表需要有一个与t_order的外键约束t_order(oid   auto_in......
  • SpringBoot + Caffeine实现本地缓存(内存缓存)
    1.Caffeine简介  Caffeine是一个基于Java8开发的提供了近乎最佳命中率的高性能的缓存库。借鉴GoogleGuava和ConcurrentLinkedHashMap的经验,实现内存缓存。  缓存和......
  • Mybatist-plus在开发过程中遇到的问题和解决办法
    1,总是老忘记一些LambdaQueryWrapper常用的表达式   2,minmaxsum等聚合函数的查询方法QueryWrapper<ParagonPrintLog>queryWrapper=newQueryWrappe......
  • 分页查询,redis缓存分页数据,redis双重检测
    StringpageKey=RedisKeyManagement.getKey(RedisKeyManagement.ACTIVITY_BAISHI_PAGE_CACHE,Arrays.asList(activityId.toString(),String.valueOf(current)));......
  • 浏览器缓存机制介绍与缓存策略剖析
    缓存可以减少网络IO消耗,提高访问速度。浏览器缓存是一种操作简单、效果显著的前端性能优化手段。对于这个操作的必要性,Chrome官方给出的解释似乎更有说服力一些:很多时......
  • net core IMemoryCache 实现缓存
    1.Nuget包添加Microsoft.Extensions.Caching.Memory程序包2.Startup.cs类 ConfigureServices方法引用服务services.AddMemoryCache();  3. 在构造函数中请求I......
  • mybatis问题记录
    1. org.apache.ibatis.exceptions.PersistenceException:###Errorqueryingdatabase.Cause:org.apache.ibatis.binding.BindingException:Parameter'bid'notfo......