浅谈 MyBatis 缓存

浅谈 MyBatis 缓存EhCache是一个快速的、轻量级的、易于使用的、进程内的缓存。它支持read-only和read/write缓存,内存和磁盘缓存。是一个非常轻量级的缓存实现,而且从1.2之后就支持了集群,目前的最新版本是2.8。

大家好,又见面了,我是你们的朋友全栈君。

1、一级缓存

MyBatis 默认开启了一级缓存,一级缓存是在 SqlSession 层面进行缓存的。即,同一个 SqlSession ,多次调用同一个 Mapper 和同一个方法的同一个参数,只会进行一次数据库查询,然后把数据缓存到缓冲中,以后直接先从缓存中取出数据,不会直接去查数据库。但是不同的 SqlSession 对象,因为不用的 SqlSession 都是相互隔离的,所以相同的 Mapper、参数和方法,它还是会再次发送到 SQL 到数据库去执行,返回结果。

2、二级缓存

为了解决这个问题,需要手动开启二级缓存,在 SqlSessionFactory 层面给各个 SqlSession 对象共享。默认二级缓存是不开启的,需要手动进行配置。

MyBatis-config.xml 文件中添加

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

xxxMapper.xml 文件中添加

<cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"/>

属性释义

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

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

flushInterval:缓存刷新间隔。缓存多长时间清空一次,默认不清空,设置一个毫秒值。

readOnly:是否只读。

  • true(只读):MyBatis 认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。MyBatis 为了加快获取数据,直接就会将数据在缓存中的引用交给用户 。不安全,速度快。
  • false(读写,默认):MyBatis 觉得获取的数据可能会被修改,MyBatis 会利用序列化或反序列化的技术克隆一份新的数据。安全,速度相对慢。

size:缓存存放多少个元素。

type:指定自定义缓存的全类名(实现 Cache 接口即可)。PS:要使用二级缓存,对应的 POJO 必须实现序列化接口 。

useCache=“true” 是否使用一级缓存,默认 true。sqlSession.clearCache();只是清除当前 session 中的一级缓存。

useCache 配置:如果一条句每次都需要最新的数据,就意味着每次都需要从数据库中查询数据,可以把这个属性设置为 false,如:

<select id="selectUserById" resultMap="map" useCache="false">

刷新缓存(就是清空缓存)二级缓存默认会在 insert、update、delete 操作后刷新缓存。

可以手动配置不更新缓存,e:

<update id="updateUserById" parameterType="User" flushCache="false">

3、自定义缓存

自定义缓存对象,该对象必须实现 org.apache.ibatis.cache.Cache 接口。

为了方便日后的开发工作和降低学习成本,我们可以使用第三方缓存,推荐使用 EhCache。

EhCache 是一个快速的、轻量级的、易于使用的、进程内的缓存。它支持 read-only 和 read/write 缓存,内存和磁盘缓存。是一个非常轻量级的缓存实现,而且从 1.2 之后就支持了集群,目前的最新版本是 2.8。

部署

3.1. 导入所需 jar:

核心包:ehcache-core-2.6.8.jar

整合包:MyBatis-ehcache-1.0.3.jar

依赖 jar 包:slf4j-api-1.6.6.jar,slf4j-jdk14-1.6.6.jar

3.2. 导入所需配置文件:

ehcache.xml,下面是对配置文件的一些讲解:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
 
 <!-- 磁盘保存路径 -->
 <diskStore path="D:\ehcache"/>
 
 <defaultCache 
   maxElementsInMemory="10000" 
   maxElementsOnDisk="10000000"
   eternal="false" 
   overflowToDisk="true" 
   timeToIdleSeconds="120"
   timeToLiveSeconds="120" 
   diskExpiryThreadIntervalSeconds="120"
   memoryStoreEvictionPolicy="LRU">
 </defaultCache>
 
</ehcache>
 
<!-- 
属性说明:
diskStore:指定数据在磁盘中的存储位置。
defaultCache:当借助 CacheManager.add("demoCache") 创建 Cache 时,EhCache 便会采用 <defalutCache/> 指定的的管理策略。
 
以下属性是必须的:
maxElementsInMemory - 在内存中缓存的 element 的最大数目。
maxElementsOnDisk - 在磁盘上缓存的 element 的最大数目,若是 0 表示无穷大。
eternal - 设定缓存的 elements 是否永远不过期。如果为 true,则缓存的数据始终有效,如果为 false 那么还要根据 timeToIdleSeconds,timeToLiveSeconds 判断。
overflowToDisk - 设定当内存缓存溢出的时候是否将过期的 element 缓存到磁盘上。
 
以下属性是可选的:
timeToIdleSeconds - 当缓存在 EhCache 中的数据前后两次访问的时间超过 timeToIdleSeconds 的属性取值时,这些数据便会删除,默认值是 0,也就是可闲置时间无穷大。
timeToLiveSeconds - 缓存 element 的有效生命期,默认是 0,也就是 element 存活时间无穷大。
diskSpoolBufferSizeMB - 这个参数设置 DiskStore (磁盘缓存)的缓存区大小.默认是 30MB.每个 Cache 都应该有自己的一个缓冲区。
diskPersistent - 在 VM 重启的时候是否启用磁盘保存 EhCache 中的数据,默认是 false。
diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是 120 秒。每个 120s,相应的线程会进行一次 EhCache 中数据的清理工作。
memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的 element 加入的时候, 移除缓存中 element 的策略。默认是 LRU(最近最少使用),可选的有 LFU(最不常使用)和 FIFO(先进先出)。
 -->

3.3. 在 xxxMapper.xml 文件中进行配置

<cache type="org.MyBatis.caches.ehcache.EhcacheCache"/>

如果在其他的 xxxMapper.xml 文件中也想要使用,只需在该文件下配置,namespace 为配置过得命名空间地址。

<cache-ref namespace="mapper.UserMapper"/>

MyBatis 默认是启用 cache 的,所以对于某一条不想被 cache 的 sql 需要把 useCache=“false” 加上。e:

<select id="selectUserById" useCache="false">

进行测试后,会在 磁盘保存路径 中产生了相关的文件。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/143288.html原文链接:https://javaforall.net

(0)
上一篇 2022年5月21日 下午11:20
下一篇 2022年5月21日 下午11:20


相关推荐

  • 使用Python防止SQL注入攻击

    使用Python防止SQL注入攻击让我们一起掌握 Python 防止 SQL 注入的技巧跟方法来抵抗恶意攻击吧

    2026年3月17日
    2
  • Netty实战

    Netty实战Netty 实战此处观看更加使用 Netty 实现一个简单的 RPC 框架 RPC 是什么 原理是什么网上很多大神都有在总结 我就不再重复 如果对 RPC 还不是很了解的同学不妨先去了解一下基本的概念这个实例仅仅只是学习 Netty 的一个很小的样例 实际上 它离真正的 RPC 还差得远 写这个的目的仅仅只是为了熟悉 Netty 一个真正的 RPC 至少应该具备以下的功能 注册中心网络传输序列化和反序列化动态代理负载均衡传输协议需求 模仿 dubbo 消费者和提供者约定接口和协议 消费者远程调用提供者的服务

    2026年3月19日
    2
  • Nunchaku-flux-1-dev实战:Java后端集成AIGC图片生成服务

    Nunchaku-flux-1-dev实战:Java后端集成AIGC图片生成服务

    2026年3月19日
    3
  • Spinnaker 核心概念解析

    Spinnaker 核心概念解析Spinnaker 调研汇总参考资料 APIDoc https www spinnaker io reference api docs htmlSwaggerU http 15 114 100 67 8084 swagger ui htmlSpinnake https www spinnaker io reference SpinnakerCod

    2026年3月17日
    2
  • 大型网站架构演化历程

    大型网站架构演化历程大型网站的挑战主要来自庞大的用户 高并发的访问和海量数据 任何简单的业务一旦需要处理数以 P 计的数据和面对数以亿计的用户 问题就会变得棘手 大型网站架构主要就是解决这类问题 本文内容大部分来自 大型网站技术架构 大型网站系统与 Java 中间件实践 这两本书 这两本书很值得一看 强烈推荐 在微信公众号猿 blog 后台 扫描下图二维码 回复关键词 大型网站架构 可以获得这两本书籍的电子版和一张思维

    2026年3月17日
    2
  • centos关闭自动休眠_7P怎么强制重启

    centos关闭自动休眠_7P怎么强制重启taskkill/F/imnginx.exetaskkill/F/imnginx.exed:cdD:\phpstudy_pro\Extensions\Nginx1.15.11startnginx.exe然后做个计划任务。一个小时重启一次

    2022年8月13日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号