【MyBatis框架】查询缓存-二级缓存原理

二级缓存原理

1.原理

首先看图

首先开启mybatis的二级缓存。

sqlSession1去查询用户id为1的用户信息,查询到用户信息会将查询数据存储到二级缓存中。

如果SqlSession3去执行相同 mapper下sql,执行commit提交,清空该 mapper下的二级缓存区域的数据。

sqlSession2去查询用户id为1的用户信息,去缓存中找是否存在数据,如果存在直接从缓存中取出数据。

二级缓存与一级缓存区别,二级缓存的范围更大,多个sqlSession可以共享一个UserMapper的二级缓存区域。
UserMapper有一个二级缓存区域(按namespace分) ,其它mapper也有自己的二级缓存区域(按namespace分)。
每一个namespace的mapper都有一个二缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同 的二级缓存区域中。

2.开启二级缓存

mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓存。

在核心配置文件SqlMapConfig.xml中加入

[html] view plain copy

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

描述允许值
默认值
cacheEnabled 对在此配置文件下的所有cache 进行全局性开/关设置。true false
true

在UserMapper.xml中开启二缓存,UserMapper.xml下的sql执行完成会存储到它的缓存区域(HashMap)。

<!-- 开启本Mapper的namespace下的二级缓存 -->
    <cache/>

3.调用pojo类实现序列化接口

[java] view plain copy

  1. public class User implements Serializable{
  2. private int id;
  3. private String username;// 用户姓名
  4. private String sex;// 性别
  5. private Date birthday;// 生日
  6. private String address;// 地址
  7. //...
  8. }

为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质多种多样(内存、硬盘、服务器),不一样在内存。

4.测试方法
先测试二级缓存的存在

[java] view plain copy

  1. //测试二级缓存
  2. @Test
  3. public void testCache2() throws Exception{
  4. SqlSession sqlSession1 = sqlSessionFactory.openSession();
  5. SqlSession sqlSession2 = sqlSessionFactory.openSession();
  6. SqlSession sqlSession3 = sqlSessionFactory.openSession();
  7. UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);//创建代理对象
  8. //下边查询使用一个SqlSession
  9. //第一次发起请求,查询id为1的用户
  10. User user1 = userMapper1.findUserById(1);
  11. System.out.println(user1.getUsername());
  12. //不关闭SqlSession无法写进二级缓存区域中
  13. sqlSession1.close();
  14. UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);//创建代理对象
  15. //第二次发起请求,查询id为1的用户
  16. User user2 = userMapper2.findUserById(1);
  17. System.out.println(user2.getUsername());
  18. sqlSession2.close();
  19. }

测试结果和输出日志:

[plain] view plain copy

  1. DEBUG [main] - Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.0
  2. DEBUG [main] - Opening JDBC Connection
  3. DEBUG [main] - Created connection 26255574.
  4. DEBUG [main] - Setting autocommit to false on JDBC Connection [[email protected]]
  5. DEBUG [main] - ==>  Preparing: SELECT * FROM USER WHERE id=?
  6. DEBUG [main] - ==> Parameters: 1(Integer)
  7. DEBUG [main] - <==      Total: 1
  8. 张三
  9. DEBUG [main] - Resetting autocommit to true on JDBC Connection [[email protected]]
  10. DEBUG [main] - Closing JDBC Connection [[email protected]]
  11. DEBUG [main] - Returned connection 26255574 to pool.
  12. DEBUG [main] - Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.5
  13. 张三

我们可以发现,日志输出中有一句我们之前没有见过,是:
Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.0
这句的意思是缓存命中率为0.0,说明第一次是在缓存中找,可是没找到
DEBUG [main] - Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.5
这句的意思是缓存命中率为0.5,说明第一次是在缓存中找,可是没找到,第二次找到了。

这个测试证明了二级缓存的存在

下面证明第三方sqlSession执行增删改会清空缓存的事实:

[java] view plain copy

  1. //测试二级缓存
  2. @Test
  3. public void testCache2() throws Exception{
  4. SqlSession sqlSession1 = sqlSessionFactory.openSession();
  5. SqlSession sqlSession2 = sqlSessionFactory.openSession();
  6. SqlSession sqlSession3 = sqlSessionFactory.openSession();
  7. UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);//创建代理对象
  8. //下边查询使用一个SqlSession
  9. //第一次发起请求,查询id为1的用户
  10. User user1 = userMapper1.findUserById(1);
  11. System.out.println(user1.getUsername());
  12. //不关闭SqlSession无法写进二级缓存区域中
  13. sqlSession1.close();
  14. UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);//创建代理对象
  15. User user=userMapper3.findUserById(1);
  16. user.setUsername("张明明");
  17. userMapper3.updateUser(user);
  18. //执行提交,清空UserMapper二级缓存
  19. sqlSession3.commit();
  20. sqlSession3.close();
  21. UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);//创建代理对象
  22. //第二次发起请求,查询id为1的用户
  23. User user2 = userMapper2.findUserById(1);
  24. System.out.println(user2.getUsername());
  25. sqlSession2.close();
  26. }

输出结果和日志信息:

[plain] view plain copy

  1. DEBUG [main] - Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.0
  2. DEBUG [main] - Opening JDBC Connection
  3. DEBUG [main] - Created connection 189219.
  4. DEBUG [main] - Setting autocommit to false on JDBC Connection [[email protected]]
  5. DEBUG [main] - ==>  Preparing: SELECT * FROM USER WHERE id=?
  6. DEBUG [main] - ==> Parameters: 1(Integer)
  7. DEBUG [main] - <==      Total: 1
  8. 张三
  9. DEBUG [main] - Resetting autocommit to true on JDBC Connection [[email protected]]
  10. DEBUG [main] - Closing JDBC Connection [[email protected]]
  11. DEBUG [main] - Returned connection 189219 to pool.
  12. DEBUG [main] - Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.5
  13. DEBUG [main] - Opening JDBC Connection
  14. DEBUG [main] - Checked out connection 189219 from pool.
  15. DEBUG [main] - Setting autocommit to false on JDBC Connection [[email protected]]
  16. DEBUG [main] - ==>  Preparing: update user set username=?,birthday=?,sex=?,address=? where id=?
  17. DEBUG [main] - ==> Parameters: 张明明(String), 2015-06-07(Date), 男(String), 河南焦作(String), 1(Integer)
  18. DEBUG [main] - <==    Updates: 1
  19. DEBUG [main] - Committing JDBC Connection [[email protected]]
  20. DEBUG [main] - Resetting autocommit to true on JDBC Connection [[email protected]]
  21. DEBUG [main] - Closing JDBC Connection [[email protected]]
  22. DEBUG [main] - Returned connection 189219 to pool.
  23. DEBUG [main] - Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.3333333333333333
  24. DEBUG [main] - Opening JDBC Connection
  25. DEBUG [main] - Checked out connection 189219 from pool.
  26. DEBUG [main] - Setting autocommit to false on JDBC Connection [[email protected]]
  27. DEBUG [main] - ==>  Preparing: SELECT * FROM USER WHERE id=?
  28. DEBUG [main] - ==> Parameters: 1(Integer)
  29. DEBUG [main] - <==      Total: 1
  30. 张明明
  31. DEBUG [main] - Resetting autocommit to true on JDBC Connection [[email protected]]
  32. DEBUG [main] - Closing JDBC Connection [[email protected]]
  33. DEBUG [main] - Returned connection 189219 to pool.

发现第二次再去查1号用户的时候,又再一次查询了数据库,查到了最新的数据"张明明"。

二级缓存远远没有那么简单,他还有一些配置的参数。

5.useCache配置

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

[html] view plain copy

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

总结:针对每次查询都需要最新的数据sql,要设置成useCache=false,禁用二级缓存。

6.刷新缓存(就是清空缓存)
在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。

设置statement配置中的flushCache="true" 属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。
如下:

[html] view plain copy

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

总结:一般下执行完commit操作都需要刷新缓存,flushCache=true表示刷新缓存,这样可以避免数据库脏读。

出处:http://blog.csdn.net/acmman/article/details/46793289

时间: 2024-10-08 00:12:13

【MyBatis框架】查询缓存-二级缓存原理的相关文章

java:Mybatis框架3(二级缓存,延时和积极加载,SSI(Ibatis)集成,SSM集成)

1.二级缓存: 需要导入二级缓存jar包: mybatis03: ehcache.xml: <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <diskStore path="java.io.tmpdir"/> <!-- Mandat

mybatis整合Redis实现二级缓存

Mybatis整合ehcache实现二级缓存 导入相关依赖 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <!--mybatis与ehcache整合--

阶段3 1.Mybatis_12.Mybatis注解开发_8 mybatis注解开发使用二级缓存

执行两次都查询userId为57的数据.测试一级缓存 返回true 新建测试类 ,测试二级缓存 二级缓存的配置 首先是全局配置,不配置其实也是可以的.默认就是开启的.这里为了演示配置上 dao类里面进行配置 运行测试方法 只查询了一次 原文地址:https://www.cnblogs.com/wangjunwei/p/11334841.html

hibernate的获取session的两方法比较,和通过id获取对象的比较,一级缓存二级缓存

opensession与currentsession的联系与区别 在同一个线程中opensession的session是不一样的,而currentsession获取的session是一样的,这就保证了线程的安全性.当然想要后者的session需要在配置文件中手动配置,另外我们可以写一个工具类来获得后者的session. get vs load 如果查询不到数据,get会会返回null但是不会报错 若果load查询不到数据,则会报错 get立即向db发送请求 ,如果你使用的是load查询数据,即使

【企业框架源码】 SpringMVC mybatis or hibernate ehcache二级缓存maven非和maven版本【websocket即时通讯】

获取[下载地址]   [免费支持更新]三大数据库 mysql  oracle  sqlsever   更专业.更强悍.适合不同用户群体[新录针对本系统的视频教程,手把手教开发一个模块,快速掌握本系统] A集成代码生成器 [正反双向(单表.主表.明细表.树形表,开发利器)+快速构建表单;freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本,处理类,service等完整模块B 集成阿里巴巴数据库连接池druid;  数据库连接池  阿里巴巴的 druid.Drui

maven非maven版本 SpringMVC mybatis or hibernate ehcache二级缓存【websocket即时通讯】【企业级框架源码】

开发快报: 页面打印功能,websocket 强制下线功能,玩转websocket技术  [金牌]获取[下载地址]   QQ: 313596790A 代码生成器(开发利器);     增删改查的处理类,service层,mybatis的xml,SQL( mysql   和oracle)脚本,   jsp页面 都生成   就不用写搬砖的代码了,生成的放到项目里,可以直接运行B 阿里巴巴数据库连接池druid;  数据库连接池  阿里巴巴的 druid.Druid在监控.可扩展性.稳定性和性能方面都

企业框架源码 SpringMVC mybatis or hibernate ehcache二级缓存maven非和maven版本 websocket即时通讯

获取[下载地址]   QQ: 313596790   [免费支持更新]三大数据库 mysql  oracle  sqlsever   更专业.更强悍.适合不同用户群体[新录针对本系统的视频教程,手把手教开发一个模块,快速掌握本系统]A 集成代码生成器(开发利器);                                         技术:313596790   增删改查的处理类,service层,mybatis的xml,SQL( mysql   和oracle)脚本,   jsp页面

【企业级框架源码】maven非maven版本 SpringMVC mybatis or hibernate ehcache二级缓存

获取[下载地址]   QQ: 313596790A 代码生成器(开发利器);     增删改查的处理类,service层,mybatis的xml,SQL( mysql   和oracle)脚本,   jsp页面 都生成   就不用写搬砖的代码了,生成的放到项目里,可以直接运行B 阿里巴巴数据库连接池druid;  数据库连接池  阿里巴巴的 druid.Druid在监控.可扩展性.稳定性和性能方面都有明显的优势C 安全权限框架shiro ;  Shiro 是一个用 Java 语言实现的框架,通过

企业框架源码 SpringMVC mybatis or hibernate ehcache二级缓存maven非和maven版本

获取[下载地址]   QQ: 313596790   [免费支持更新]三大数据库 mysql  oracle  sqlsever   更专业.更强悍.适合不同用户群体[新录针对本系统的视频教程,手把手教开发一个模块,快速掌握本系统]A 集成代码生成器(开发利器);                                         技术:313596790   增删改查的处理类,service层,mybatis的xml,SQL( mysql   和oracle)脚本,   jsp页面