一次读懂mybatis中的缓存机制

缓存功能针对于查询(没听说果UPDATE,INSERT语句要缓存什么,都是直接执行的)

默认情况下,mybatis会启用一级缓存。

如果使用同一个session对象调用了相同的SELECT语句,则直接会从缓存中返回结果,而不是再查询一次数据库。

注意:session调用commit或close方法后,这个session中的一级缓存就会被清空

例如: 根据日志输出可以看出,下面代码只会发出一条sql查询语句

SqlSession sqlSession = MyBatisSqlSessionFactory.openSession();
OneToManyMapper mapper = sqlSession.getMapper(OneToManyMapper.class);Tutor findTutorById1 = mapper.findTutorById(1);
System.out.println(findTutorById1);
Tutor findTutorById2 = mapper.findTutorById(1);
System.out.println(findTutorById2);

日志文件输出:

2019-10-16 19:15:39,870 [DEBUG] com.briup.mappers.OneToManyMapper.findTutorById - ==> Preparing: select * from tutors where tutor_id=?
2019-10-16 19:15:39,999 [DEBUG] com.briup.mappers.OneToManyMapper.findTutorById - ==> Parameters: 1(Integer)
2019-10-16 19:15:40,218 [DEBUG] com.briup.mappers.OneToManyMapper.findAddressById - ====> Preparing: select * from addresses where addr_id = ?
2019-10-16 19:15:40,218 [DEBUG] com.briup.mappers.OneToManyMapper.findAddressById - ====> Parameters: 1(Integer)
2019-10-16 19:15:40,220 [DEBUG] com.briup.mappers.OneToManyMapper.findAddressById - <==== Total: 1
2019-10-16 19:15:40,221 [DEBUG] com.briup.mappers.OneToManyMapper.findCoursesByTutor - ====> Preparing: select * from courses where tutor_id=?
2019-10-16 19:15:40,221 [DEBUG] com.briup.mappers.OneToManyMapper.findCoursesByTutor - ====> Parameters: 1(Integer)
2019-10-16 19:15:40,226 [DEBUG] com.briup.mappers.OneToManyMapper.findCoursesByTutor - <==== Total: 2
2019-10-16 19:15:40,226 [DEBUG] com.briup.mappers.OneToManyMapper.findTutorById - <== Total: 1

Tutor [tutorId=1, name=null, [email protected], phone=PhoneNumber [countryCode=123, stateCode=456, number=7890], address=Address [addrId=1, street=redSt, city=kunshan, state=W, zip=12345, country=china], courses=[Course [courseId=1, name=JavaSE, description=JavaSE, startDate=Thu Jan 10 00:00:00 CST 2019, endDate=Sun Feb 10 00:00:00 CST 2019], Course [courseId=3, name=MyBatis, description=MyBatis, startDate=Thu Jan 10 00:00:00 CST 2019, endDate=Wed Feb 20 00:00:00 CST 2019]]]

Tutor [tutorId=1, name=null, [email protected], phone=PhoneNumber [countryCode=123, stateCode=456, number=7890], address=Address [addrId=1, street=redSt, city=kunshan, state=W, zip=12345, country=china], courses=[Course [courseId=1, name=JavaSE, description=JavaSE, startDate=Thu Jan 10 00:00:00 CST 2019, endDate=Sun Feb 10 00:00:00 CST 2019], Course [courseId=3, name=MyBatis, description=MyBatis, startDate=Thu Jan 10 00:00:00 CST 2019, endDate=Wed Feb 20 00:00:00 CST 2019]]]

从以上日志可以分析出来,这个select语句只发了一次,第二次的查询用的是第一次查询的缓存

二级缓存: 在不同的session对象之间可以共享缓存的数据
1.mybatis-config.xml文件中保证<setting name="cacheEnabled" value="true"/>设置中是缓存功能是开启的,默认就是开启的true
2.在需要二级缓存的xml映射文件中,手动开启缓存功能,在根元素中加入一个标签即可:<cache/>
3.一个session查询完数据之后,需要调用commit或者close方法后,这个数据才会进入到二级缓存中,然后其他session就可以共享到这个缓存数据了

注意:默认情况下,被二级缓存保存的对象需要实现序列化接口。

例如:
mybatis-config.xml:

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

xml映射文件:

<mapper namespace="com.briup.mappers.SpecialMapper">
<cache/>
<select> ..</select>
<select> ..</select>
<select> ..</select>
</mapper>

测试代码:

@Test
public void test_cache2(){
SqlSession session1 = null;
SqlSession session2 = null;
try {
session1 = MyBatisSqlSessionFactory.openSession();
session2 = MyBatisSqlSessionFactory.openSession();

SpecialMapper mapper1 = session1.getMapper(SpecialMapper.class);
SpecialMapper mapper2 = session2.getMapper(SpecialMapper.class);

User user1 = mapper1.findUserById(56);
System.out.println(user1);
session1.commit();

User user2 = mapper2.findUserById(56);
System.out.println(user2);
session2.commit();
} catch (Exception e) {
e.printStackTrace();
}finally {
if(session1!=null)session1.close();
if(session2!=null)session2.close();
}
}

日志文件输出:

2019-10-16 19:29:22,443 [DEBUG] com.briup.mappers.OneToManyMapper - Cache Hit Ratio [com.briup.mappers.OneToManyMapper]: 0.0
2019-10-16 19:29:23,449 [DEBUG] com.briup.mappers.OneToManyMapper.findTutorById - ==> Preparing: select * from tutors where tutor_id=?
2019-10-16 19:29:23,648 [DEBUG] com.briup.mappers.OneToManyMapper.findTutorById - ==> Parameters: 1(Integer)
2019-10-16 19:29:23,805 [DEBUG] com.briup.mappers.OneToManyMapper - Cache Hit Ratio [com.briup.mappers.OneToManyMapper]: 0.0
2019-10-16 19:29:23,805 [DEBUG] com.briup.mappers.OneToManyMapper.findAddressById - ====> Preparing: select * from addresses where addr_id = ?
2019-10-16 19:29:23,806 [DEBUG] com.briup.mappers.OneToManyMapper.findAddressById - ====> Parameters: 1(Integer)
2019-10-16 19:29:23,808 [DEBUG] com.briup.mappers.OneToManyMapper.findAddressById - <==== Total: 1
2019-10-16 19:29:23,808 [DEBUG] com.briup.mappers.OneToManyMapper - Cache Hit Ratio [com.briup.mappers.OneToManyMapper]: 0.0
2019-10-16 19:29:23,809 [DEBUG] com.briup.mappers.OneToManyMapper.findCoursesByTutor - ====> Preparing: select * from courses where tutor_id=?
2019-10-16 19:29:23,809 [DEBUG] com.briup.mappers.OneToManyMapper.findCoursesByTutor - ====> Parameters: 1(Integer)
2019-10-16 19:29:23,814 [DEBUG] com.briup.mappers.OneToManyMapper.findCoursesByTutor - <==== Total: 2
2019-10-16 19:29:23,814 [DEBUG] com.briup.mappers.OneToManyMapper.findTutorById - <== Total: 1

Tutor [tutorId=1, name=null, [email protected], phone=PhoneNumber [countryCode=123, stateCode=456, number=7890], address=Address [addrId=1, street=redSt, city=kunshan, state=W, zip=12345, country=china], courses=[Course [courseId=1, name=JavaSE, description=JavaSE, startDate=Thu Jan 10 00:00:00 CST 2019, endDate=Sun Feb 10 00:00:00 CST 2019], Course [courseId=3, name=MyBatis, description=MyBatis, startDate=Thu Jan 10 00:00:00 CST 2019, endDate=Wed Feb 20 00:00:00 CST 2019]]]

2019-10-16 19:29:23,825 [DEBUG] com.briup.mappers.OneToManyMapper - Cache Hit Ratio [com.briup.mappers.OneToManyMapper]: 0.25

Tutor [tutorId=1, name=null, [email protected], phone=PhoneNumber [countryCode=123, stateCode=456, number=7890], address=Address [addrId=1, street=redSt, city=kunshan, state=W, zip=12345, country=china], courses=[Course [courseId=1, name=JavaSE, description=JavaSE, startDate=Thu Jan 10 00:00:00 CST 2019, endDate=Sun Feb 10 00:00:00 CST 2019], Course [courseId=3, name=MyBatis, description=MyBatis, startDate=Thu Jan 10 00:00:00 CST 2019, endDate=Wed Feb 20 00:00:00 CST 2019]]]

可以看出,sqlSession2这个对象第二次查询的时候,命中了缓存

2019-10-16 19:29:23,825 [DEBUG] com.briup.mappers.OneToManyMapper - Cache Hit Ratio [com.briup.mappers.OneToManyMapper]: 0.25(缓存命中率0.25)

二级缓存补充说明
  1. 映射语句文件中的所有select语句将会被缓存
  2. 映射语句文件中的所有insert,update和delete语句会刷新缓存
  3. 缓存会使用Least Recently Used(LRU,最近最少使用的)算法来收回。
  4. 缓存会根据指定的时间间隔来刷新。
  5. 缓存会存储1024个对象

cache标签常用属性:
<cache
eviction="FIFO" <!--回收策略为先进先出-->
flushInterval="60000" <!--自动刷新时间60s-->
size="512" <!--最多缓存512个引用对象-->
readOnly="true"/> <!--true表示对象不能被写出去,即不可以被序列化,false表示可以写出去,即可以被序列化,默认值是false-->

原文地址:https://www.cnblogs.com/Magic-Li/p/11687818.html

时间: 2024-11-05 19:42:03

一次读懂mybatis中的缓存机制的相关文章

教你读懂redmine中的甘特图

Redmine是用Ruby开发的基于web的项目管理软件,他可以自动绘制甘特图,对于我们了解项目进度有很重要的帮助.但很多新人小白在使用redmine时,就是当成一个简单的备忘录来使用,对于甘特图神马的根本就不care,那么如何正确的使用甘特图呢?如何读懂redmine中的甘特图呢? Redmine是可以根据建立的问题的开始时间.结束时间和完成百分比自动绘制甘特图的.所以我们要使用redmine的甘特图,必须在新建问题时根据项目计划设置好开始时间,预估结束时间,每天在结束一天的工作后,注意及时更

Mybatis中的缓存管理

目录 Mybatis中的缓存管理 查询缓存工作原理: 配置缓存: 默认配置: 使用二级缓存: 刷新缓存过程: 配置EHcache 产生脏数据 使用原则: Mybatis中的缓存管理 查询缓存工作原理: 查询语句?<--->?缓存?<---->?DB 缓存内容: Mybatis中存放的是查询的内容: 缓存对比: 类别 作用范围 生命周期 一级缓存 namespace 和sqlsession的生存周期相同 二级缓存 namespace 和整个应用的生命周期相同 一级缓存:默认是开启的,

linux套接字通信之recv中的缓存机制的研究

以前一直有这么一个小小的疑惑,当一个进程注册一个套接字后,如果这个套接字没有被调用recv函数接受数据包,那么这个套接字能接受到数据包吗? 或者这样说,如果我的程序注册了一个套接字去接受数据包,但是每收到一个数据包都需要很长一段时间处理,并且在处理数据包的途中recv函数使没有被调用的,那么如果程序再处理数据包的途中有数据包到来,那我的程序会不会漏过这些数据包(那个包到达的时候程序在处理别的包,而没有调用recv函数)? 答案是不会的.事实上linux中会为每个套接字建立缓存,当属于套接字的包到

SSM-MyBatis-17:Mybatis中二级缓存

------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 二级缓存 Mybatis中,默认二级缓存是开启的.可以关闭. 一级缓存开启的.可以被卸载吗?不可以的.一级缓存不可以卸载,天然和框架绑定.内置二级缓存 由于MyBatis从缓存中读取数据的依据与SQL的id相关,而非查询出的对象.所以,使用二级缓存的目的,不是在多个查询间共享查询结果(所有查询中只要查询结果中存在该对象, 就直接从缓存中读取,这是对查询结果的共享,Hibernate中的缓存就是为了在多个查询

hibernate中的缓存机制

一.为什么要用Hibernate缓存? Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 二.Hibernate缓存原理是怎样的?Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存. 1.Hibernate一级缓存又称为“Session的缓存”. Sessio

Mybatis的一级缓存机制简介

1.接口 public interface MemberMapperCache { public Members selectMembersById(Integer id); } 2.配置文件xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://my

缓存机制总结(JVM内置缓存机制,MyBatis和Hibernate缓存机制,Redis缓存)

一.JVM内置缓存(值存放在JVM缓存中) 我们可以先了解一下Cookie,Session,和Cache Cookie:当你在浏览网站的时候,WEB 服务器会先送一小小资料放在你的计算机上,Cookie 会帮你在网站上所打的文字或是一些选择都纪录下来.当下次你再光临同一个网站,WEB 服务器会先看看有没有它上次留下的 Cookie 资料,有的话,就会依据 Cookie里的内容来判断使用者,送出特定的网页内容给你.具体来说Cookie机制采用的是在客户端保持状态的方案(保存客户浏览器请求服务器页面

029.ASP.Net中的缓存机制

ASP.Net中的缓存 输出缓存1. 整页缓存 缓存整个页面的输出结果 Duration 缓存时间:绝对过期 VaryByParam:依据参数值缓存,没有为None,多个用;分割 Location:缓存的位置 代码在 ftp 的 Cache目录内 2. 片段缓存 使用用户控件,将需要缓存的内容放入用户控件 指定shared=true,可以多个页面共享缓存结果 3.Substitution控件 在整页都缓存的情况下,可以部分更新内容 配置MethodName属性,对应的.cs中的方法原型是 str

分享知识-快乐自己:论Hibernate中的缓存机制

Hibernate缓存 缓存: 是计算机领域的概念,它介于应用程序和永久性数据存储源之间. 缓存: 一般人的理解是在内存中的一块空间,可以将二级缓存配置到硬盘.用白话来说,就是一个存储数据的容器.我们关注的是,哪些数据需要被放入二级缓存. 缓存作用: 降低应用程序直接读写数据库的频率,从而提高程序的运行性能.缓存中的数据是数据存储源中数据的拷贝.缓存的物理介质通常是[内存]. Hibernate缓存分类: 1):Session缓存(又称作事务缓存):Hibernate内置的,不能卸除. 缓存范围