Mybatis的缓存机制Cache

Mybatis提供对缓存的支持,分为一级缓存和二级缓存,在没有配置的情况下,系统默认会使用一级缓存。

一级缓存(SqlSession级别)

  我们都知道每个SqlSession对象之间的缓存是互不影响的,当同一个SqlSession执行多次相同的SQL语句时(主要针对select),系统只会到底层访问数据库一次,后续执行sql时,会从一级缓存里面读取第一次访问的数据。当这个SqlSession对象执行close(),或者显示声明清空缓存时,对应的一级缓存也会清空,从而提高效率。值得注意的是,如果SqlSession执行DML操作(即insert、update、delete),并提交到数据库时,也会起到清空该SqlSession对象对应的一级缓存的作用,目的是为了保证缓存里面的数据是最新的。,避免脏读现象。

二级缓存(SqlSessionFactory级别)

  有些书籍说二级缓存是Mapper级别,可能是依据二级缓存的配置是在xxxMapper.xml上配置的吧,不过本人更认同是SqlSessionFactory级别,为什么呢?因为同一个Configuration里面是创建一个SqlSessionFactory,SqlSessionFactory是属于线程安全的,SqlSessionFactory可以创建很多个SqlSession来进行事务操作,也就是说,SqlSessionFactory是由很多个SqlSession对象共享的,同样的,二级缓存的数据也是由很多个SqlSession共享的。如何才能让系统操作二级缓存呢?原理很简单,不同的SqlSession对象执行相同的namespace下的sql语句,当第一个SqlSession对象调用close()关闭一级缓存时,第一次查询得到的数据将会被保存到二级缓存,后面的SqlSession对象调用相同sql语句时,就会从二级缓存中获取数据。当然,使用二级缓存,需要对应的返回对象(即POJO)实现序列化。

配置:在需要使用的xxxMapper.xml里面配置<cache eviction="LRU" flushInterval="100000" size="1024" readOnly="true" />

eviction:代表回收策略,目前支持4种策略

1.LRU,最近最少使用的,移除最长时间不用的对象;

2.FIFO,先进先出;

3.SOFT,移除基于垃圾回收器状态和软引用规则的对象;

4.WEAK,更积极移除基于垃圾回收器状态和弱引用规则的对象。

flushInterval:代表刷新时长,单位毫秒

size:代表缓存最多可以存储多少个对象,注意,设置过大会导致内存溢出

readOnly:意味着缓存数据只能读取,不能修改

上面是较为详细配置,当然也可以简单一点,直接写上<cache />就可以了。

下面给出一个较为有意思的栗子:

xml配置代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.learn.mapper.EmployeeMapper"><cache /><select id="getEmpList" resultType="employee">select * from tb_employee</select></mapper>

JUnit4测试代码如下:

@Testpublic void testCache(){SqlSession ss1 = null;SqlSession ss2 = null;try{ss1 = SqlSessionFactoryUtil.initSqlSessionFactory().openSession();ss2 = SqlSessionFactoryUtil.initSqlSessionFactory().openSession();EmployeeMapper em1 = ss1.getMapper(EmployeeMapper.class);EmployeeMapper em2 = ss2.getMapper(EmployeeMapper.class);List<Employee> list1 =  em1.getEmpList();//ss1.close();list1 = em2.getEmpList();}catch(Exception e){ss1.rollback();ss2.rollback();e.printStackTrace();}finally{if(ss1 != null){ss1.close();}if(ss2 != null){ss2.close();}}}

代码中实例化两个SqlSession对象,分别是ss1和ss2,用户检验数据读取的操作。留意上面注释了ss1.close();这一行。

下面是执行上面测试代码的日志结果:

Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Cache Hit Ratio [com.learn.mapper.EmployeeMapper]: 0.0
Opening JDBC Connection
Created connection 275310919.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1068e947]
==>  Preparing: select * from tb_employee 
==> Parameters: 
<==      Total: 6
Cache Hit Ratio [com.learn.mapper.EmployeeMapper]: 0.0
Opening JDBC Connection
Created connection 1948863195.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@74294adb]
==>  Preparing: select * from tb_employee 
==> Parameters: 
<==      Total: 6
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1068e947]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1068e947]
Returned connection 275310919 to pool.
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@74294adb]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@74294adb]
Returned connection 1948863195 to pool.

可以看到即使配置了<cache />二级缓存,第一个SqlSession对象ss1没有手动执行close()方法时,ss1对应的一级缓存数据仍然没有保存到二级缓存里面,即二级缓存里面没有数据,当第二个SqlSession对象ss2执行相同的sql语句时,会找一级缓存有没有数据,因为第一次执行,当然没有数据了,然后找二级缓存,刚才说过了,ss1的一级缓存数据并没有保存到二级缓存里面,所以二级缓存也没有数据,因此ss2就会再次操作数据库。可以看到log日志会有两条select语句。

此时,如果将close();的注释去掉,再执行一下测试代码,日志结果如下:

Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Cache Hit Ratio [com.learn.mapper.EmployeeMapper]: 0.0
Opening JDBC Connection
Created connection 275310919.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1068e947]
==>  Preparing: select * from tb_employee 
==> Parameters: 
<==      Total: 6
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1068e947]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1068e947]
Returned connection 275310919 to pool.
Cache Hit Ratio [com.learn.mapper.EmployeeMapper]: 0.5

显而易见,此时只访问一次数据库。

转载于:https://www.cnblogs.com/SysoCjs/p/9574318.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/451425.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据应用时代来袭 SaaS走向没落?

随着大量的信息涌入互联网——90%的互联网是过去两年建立起来的——互联网公司正在想方设法去熟悉并利用大数据来推动他们的业务。正如SaaS和云技术一样完全变革了企业的运作方式一样&#xff0c;大数据应用&#xff08;BDA&#xff09;也同样可以。 BDA是基于网络的应用&#…

为什么使用数据库从库

主库用来进行写操作&#xff0c;从库用来进行读操作&#xff0c;这样一来的可以大大提高读取的效率。在一般的互联网应用中&#xff0c;经过一些数据调查得出结论&#xff0c;读/写的比例大概在 10&#xff1a;1左右 &#xff0c;也就是说大量的数据操作是集中在读的操作。但是…

Java程序员必知的10个调试技巧

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 在本文中&#xff0c;作者将使用大家常用的的开发工具Eclipse来调试Java应用程序。但这里介绍的调试方法基本都是通用的&#xff0c;也适…

【GPS】GPS的C_GNSS_RF_ELNA_GPIO_NUM_DEFAULT配置,Linux系统中GPIO的设置

GPS的GPIO配置文件 客户需要更改此变量C_GNSS_RF_ELNA_GPIO_NUM_DEFAULT才能覆盖NAVRF驱动程序ELNA设置。   modem_proc/gps/gnss/mgp/me/gen8/src/cgps_ext.c /* Customer needs to change this variable in order to override NAVRF driver ELNA setting */ gnss_ExternalG…

学习的境界

学习是有境界的&#xff0c;下面以C语言中的结构型为例简单分析。 第一种境界&#xff1a;理解了。 结构型是自定义数据类型&#xff0c;与C语言中基本的数据类型如int的作用相同&#xff0c;用于定义变量。&#xff08;变量是内存中存储单元的标识&#xff0c;C语言中通过变…

性能测试的重要意义(一)

♦我是一下下面几个方面来理解的&#xff1a; 1.秒的性能对于顾客的意义&#xff1f; 2.性能测试的重要意义 3.什么是软件的性能&#xff1f; 4.软件的性能测试是什么&#xff1f; 5.功能测试和性能测试对比&#xff1f; 6.项目组不同角色眼中的软件性能&#xff1f; 7.性能测试…

ContextLoaderListener介绍

在给新同事培训Spring MVC时&#xff0c;有人问&#xff1a;可以不配置ContextLoaderListener吗 所谓ContextLoaderListener&#xff0c;就是在web部署描述符即web.xml里面经常配置的一个监听器&#xff0c;如下 [html] view plaincopy <listener> <listener-cl…

PLSQL安装教程,无需oracle客户端(解决本地需要安装oracle客户端的烦恼)

最近用笔记本开发&#xff0c;项目用的是Oracle数据库&#xff0c;不想本地安装Oracle客户端。 就只装了一个PLSQL 连接数据库的时候各种错误&#xff0c;现在解决了记录一下。 详细内容见 附件 1、运行 plsqldev1105_x64.exe2、运行 Language_zh_x86_x64.exe3、启动 plsql 点…

移动开发(C#、VB.NET)Smobiler开发平台——GifView控件的使用方式

2019独角兽企业重金招聘Python工程师标准>>> 一、 样式一 我们要实现上图中的效果&#xff0c;需要如下的操作&#xff1a; 从工具栏上的“Smobiler Components”拖动一个GifView控件到窗体界面上修改GifView的属性 AutoPlay属性获得和设置是否自动播放Gif…

Spring中的计时器StopWatch

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 需要记录每个任务执行时间&#xff0c;或者记录一段代码执行时间&#xff0c;简单方法是打印当前时间与执行完时间的差值&#xff0c;若…

常用数据结构--线性结构

数据结构是计算机存储、组织数据的方式。常见的数据结构分类方式如下图&#xff1a; 常用的线性结构有&#xff1a;线性表&#xff0c;栈&#xff0c;队列&#xff0c;循环队列&#xff0c;数组。线性表中包括顺序表、链表等&#xff0c;其中&#xff0c;栈和队列只是属于逻辑上…

依赖注入简介(一)

依赖注入(Injecting dependencies)经常听起来会让人感觉到很难以理解&#xff0c;会让大家感觉这是很复杂的编程技术&#xff0c;但是事实上并不是这样&#xff0c;依赖注入非常方便使用&#xff0c;它会让你的程序非常便于理解&#xff0c;同时也更容易进行测试。 依赖注入的…

Jmeter笔记(Ⅱ)使用Jmeter实现轻量级的接口自动化测试

接口测试虽然作为版本的一环&#xff0c;但是也是有一套完整的体系&#xff0c;有接口的功能测试、性能测试、安全测试&#xff1b;同时&#xff0c;由于接口的特性&#xff0c;接口的自动化低成本高收益的&#xff0c;使用一些开源工具或一些轻量级的方法&#xff0c;在测试用…

设置Android Studio工程布局文件的默认布局

每次创建新的工程后&#xff0c;布局文件的的布局总是ConstraintLayout&#xff0c;如何更改&#xff1f; 进入Android Studio安装目录&#xff0c;用文本编辑器打开文件plugins\android\lib\templates\activities\common\root\res\layout\simple.xml.ftl 将文件内容修改为 <…

依赖注入简介(二)

在上一篇中&#xff0c;我们已经介绍过了最基本的依赖注入&#xff0c;接下来我们来看如何对需要使用的类进行装配。通常应用程序的组件之间的关联是通过wiring&#xff0c;在Spring中同样有很多方式来装配。但是一个最通常我们使用的方法是利用XML。接下来我们来展示一个简单的…

eclipse启动tomcat 访问http://localhost:8080 报404错误

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 eclipse正常启动tomcat&#xff0c;但是 访问http://localhost:8080 却报404错误 修改下配置 就好操作如下图 打开eclipse的server视图&a…

3秒搞定!~~ 一亿数据获取前100个最大值

3秒搞定&#xff01;~~ 一亿数据获取前100个最大值 整合网络上的算法。 根据我的思路。计算一亿个数字中最大的前100个值。 昨晚效率还是很低。 今天搞的算法。 只需要3秒钟。 获取前100个 前1000个 速度都非常快。 算法原理&#xff1a; 把一亿个数字的前100个 首先放入数…

手把手JDK环境变量配置

分为下载&#xff0c;配置&#xff0c;验证三个步骤解释如何进行JDK环境变量配置。 步骤一&#xff1a; 首先查看配置成功后的效果&#xff1a; tip:点击win——>运行&#xff08;或者使用winr,或者shift鼠标右键打开powershell&#xff09;——>输入cmd回车——>控制…

网易NEI在面临前后端分离问题,所提供的完整解决方案

内容来源&#xff1a;2018 年 1 月5 日&#xff0c;网易NEI产品负责人包勇明在“2018移动技术创新大会”进行《网易高效多端应用协作开发实践》演讲分享。IT 大咖说&#xff08;微信id&#xff1a;itdakashuo&#xff09;作为独家视频合作方&#xff0c;经主办方和讲者审阅授权…

如何使用js动态显示或隐藏DIV

在web页面中&#xff0c;经常需要使用select控件来显示div的显示与隐藏&#xff0c;实现这个方法主要用到了setAttribute方法&#xff0c;以下为示例代码 [html] view plaincopy <html> <title>通过选择项显示不同的结果</title> <head> <scr…