【MyBatis学习13】MyBatis中的二级缓存

2024-09-07 20:58
文章标签 学习 13 mybatis 二级缓存

本文主要是介绍【MyBatis学习13】MyBatis中的二级缓存,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 二级缓存的原理

前面介绍了,mybatis中的二级缓存是mapper级别的缓存,值得注意的是,不同的mapper都有一个二级缓存,也就是说,不同的mapper之间的二级缓存是互不影响的。为了更加清楚的描述二级缓存,先来看一个示意图:

从图中可以看出:

1.sqlSession1去查询用户id为1的用户信息,查询到用户信息会将查询数据存储到该UserMapper的二级缓存中。
2.如果SqlSession3去执行相同 mapper下sql,执行commit提交,则会清空该UserMapper下二级缓存区域的数据。
3.sqlSession2去查询用户id为1的用户信息,去缓存中找是否存在数据,如果存在直接从缓存中取出数据。

缓存的执行原理和前面提到的一级缓存是差不多的,二级缓存与一级缓存区别在于二级缓存的范围更大,多个sqlSession可以共享一个mapper中的二级缓存区域。mybatis是如何区分不同mapper的二级缓存区域呢?它是按照不同mapper有不同的namespace来区分的,也就是说,如果两个mapper的namespace相同,即使是两个mapper,那么这两个mapper中执行sql查询到的数据也将存在相同的二级缓存区域中。

2. 二级缓存的使用

明白了mybatis中二级缓存的原理后,接下来就是如何使用二级缓存了。在使用之前,首先得开启二级缓存的开关。

2.1 开启二级缓存

由于mybaits的二级缓存是mapper范围级别,所以除了在SqlMapConfig.xml设置二级缓存的总开关外,还要在具体的mapper.xml中开启二级缓存。设置如下:

这是在SqlMapConfig.xml中设置的,还得在具体的mapper.xml中设置,如下:

可以看到,具体的mapper中仅仅就一个标签,并没有配置啥东西,这是因为mybatis中有默认的实现,我们如果不配置,那么就默认使用那个默认的实现。在mybatis的核心包里有cache的接口和这个默认的实现,我截个图:

所以就明白了,为啥不用配置都可以使用,mybatis中也就只有这一个默认实现类,如果不使用mybatis的默认二级缓存的话,就需要自己实现cache接口,然后再在mapper.xml中配置一下了,关于这个我在下面再谈,现在先把二级缓存用起来!

2.2 将po类实现Serializable接口

开启了二级缓存后,还需要将要缓存的pojo实现Serializable接口,为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质多种多样,不一定只存在内存中,有可能存在硬盘中,如果我们要再取这个缓存的话,就需要反序列化了。所以建议mybatis中的pojo都去实现Serializable接口。下面以User为例截个图:

2.3 测试mybatis的二级缓存

@Test
public void testCache2() throws Exception {SqlSession sqlSession1 = sqlSessionFactory.openSession();SqlSession sqlSession2 = sqlSessionFactory.openSession();SqlSession sqlSession3 = sqlSessionFactory.openSession();// 创建代理对象UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);// 第一次发起请求,查询id为1的用户User user1 = userMapper1.findUserById(1);System.out.println(user1);  //这里执行关闭操作,将sqlsession中的数据写到二级缓存区域sqlSession1.close();//sqlSession3用来清空缓存的,如果要测试二级缓存,需要把该部分注释掉//使用sqlSession3执行commit()操作UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);User user  = userMapper3.findUserById(1);user.setUsername("倪升武");userMapper3.updateUser(user);//执行提交,清空UserMapper下边的二级缓存sqlSession3.commit();sqlSession3.close();UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);// 第二次发起请求,查询id为1的用户User user2 = userMapper2.findUserById(1);System.out.println(user2);sqlSession2.close();}

我们先把sqlSession3部分注释掉来测试一下二级缓存的结果:

 当我们把sqlSession3部分加上后,再测试一下二级缓存结果:

到这里,就明白了mybatis中二级缓存的执行原理了,这个跟hibernate还是有点像的。也可以对照着我写的hibernate的二级缓存的博文看(不过建议把下面的ehcache部分看完再对照hibernate看)。

2.4 其他配置(useCache和flushCache)

mybatis中还可以配置userCache和flushCache等配置项,userCache是用来设置是否禁用二级缓存的,在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。

<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">

 这种情况是针对每次查询都需要最新的数据sql,要设置成useCache=false,禁用二级缓存,直接从数据库中获取。
在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。 设置statement配置中的flushCache=”true” 属性,默认情况下为true,即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。

<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">

一般下执行完commit操作都需要刷新缓存,flushCache=true表示刷新缓存,这样可以避免数据库脏读。所以我们不用设置,默认即可,这里只是提一下。

3. MyBatis整合ehcache分布式缓存框架

3.1 问题的由来

上面的部分主要总结了一下mybatis中二级缓存的使用,但是mybatis中默认自带的二级缓存有个弊端,即无法实现分布式缓存,什么意思呢?就是说缓存的数据在自己的服务器上,假设现在有两个服务器A和B,用户访问的时候访问了A服务器,查询后的缓存就会放在A服务器上,假设现在有个用户访问的是B服务器,那么他在B服务器上就无法获取刚刚那个缓存,如下图所示:

所以我们为了解决这个问题,就得找一个分布式的缓存,专门用来存储缓存数据的,这样不同的服务器要缓存数据都往它那里存,取缓存数据也从它那里取,如下图所示:

这样就能解决上面所说的问题,为了提高系统并发性能、我们一般对系统进行上面这种分布式部署(集群部署方式),所以要使用分布式缓存对缓存数据进行集中管理。但是mybatis无法实现分布式缓存,需要和其它分布式缓存框架进行整合,这里主要介绍ehcache。

3.2 整合方法

上文一开始提到过,mybatis提供了一个cache接口,如果要实现自己的缓存逻辑,实现cache接口开发即可。mybatis本身默认实现了一个,但是这个缓存的实现无法实现分布式缓存,所以我们要自己来实现。ehcache分布式缓存就可以,mybatis提供了一个针对cache接口的ehcache实现类,这个类在mybatis和ehcache的整合包中。所以首先我们需要导入整合包。

导入了jar包后,配置mapper中cache中的type为ehcache对cache接口的实现类型。ehcache对cache接口有一个实现类为:

我们将该类的完全限定名写到type属性中即可,如下:

 OK,配置完成,现在mybatis就会自动去执行这个ehcache实现类了,就不会使用自己默认的二级缓存了,但是使用ehcache还有一个缓存配置别忘了,在classpath下新建一个ehcache.xml文件:

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"><diskStore path="F:\develop\ehcache"/><defaultCachemaxElementsInMemory="10000"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"maxElementsOnDisk="10000000"diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"><persistence strategy="localTempSwap"/></defaultCache>
</ehcache>

4. 二级缓存的应用场景和局限性

对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。

mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分的,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题可能需要在业务层根据需求对数据有针对性缓存。

这篇关于【MyBatis学习13】MyBatis中的二级缓存的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1146139

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

mybatis的整体架构

mybatis的整体架构分为三层: 1.基础支持层 该层包括:数据源模块、事务管理模块、缓存模块、Binding模块、反射模块、类型转换模块、日志模块、资源加载模块、解析器模块 2.核心处理层 该层包括:配置解析、参数映射、SQL解析、SQL执行、结果集映射、插件 3.接口层 该层包括:SqlSession 基础支持层 该层保护mybatis的基础模块,它们为核心处理层提供了良好的支撑。

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识