【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中加入
<setting name="cacheEnabled" value="true"/>
描述 允许值 默认值
cacheEnabled 对在此配置文件下的所有cache 进行全局性开/关设置。 true false true

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

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

3.调用pojo类实现序列化接口
public class User implements Serializable{
	private int id;
	private String username;// 用户姓名
	private String sex;// 性别
	private Date birthday;// 生日
	private String address;// 地址
	//...
}
为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质多种多样(内存、硬盘、服务器),不一样在内存。

4.测试方法
先测试二级缓存的存在
//测试二级缓存
@Test
public void testCache2() throws Exception{
	SqlSession sqlSession1 = sqlSessionFactory.openSession();
	SqlSession sqlSession2 = sqlSessionFactory.openSession();
	SqlSession sqlSession3 = sqlSessionFactory.openSession();
	
	UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);//创建代理对象
	//下边查询使用一个SqlSession
	//第一次发起请求,查询id为1的用户
	User user1 = userMapper1.findUserById(1);
	System.out.println(user1.getUsername());
	//不关闭SqlSession无法写进二级缓存区域中
	sqlSession1.close();
	
	UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);//创建代理对象
	//第二次发起请求,查询id为1的用户
	User user2 = userMapper2.findUserById(1);
	System.out.println(user2.getUsername());
	sqlSession2.close();
	
	
}
测试结果和输出日志:
DEBUG [main] - Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.0
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 26255574.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.Connection@190a0d6]
DEBUG [main] - ==>  Preparing: SELECT * FROM USER WHERE id=? 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
张三
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.Connection@190a0d6]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.Connection@190a0d6]
DEBUG [main] - Returned connection 26255574 to pool.
DEBUG [main] - Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.5
张三

我们可以发现,日志输出中有一句我们之前没有见过,是:
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执行增删改会清空缓存的事实:
//测试二级缓存
@Test
public void testCache2() throws Exception{
	SqlSession sqlSession1 = sqlSessionFactory.openSession();
	SqlSession sqlSession2 = sqlSessionFactory.openSession();
	SqlSession sqlSession3 = sqlSessionFactory.openSession();
	
	UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);//创建代理对象
	//下边查询使用一个SqlSession
	//第一次发起请求,查询id为1的用户
	User user1 = userMapper1.findUserById(1);
	System.out.println(user1.getUsername());
	//不关闭SqlSession无法写进二级缓存区域中
	sqlSession1.close();
	
	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.getUsername());
	sqlSession2.close();
	
	
}

输出结果和日志信息:
DEBUG [main] - Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.0
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 189219.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.Connection@2e323]
DEBUG [main] - ==>  Preparing: SELECT * FROM USER WHERE id=? 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
张三
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.Connection@2e323]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.Connection@2e323]
DEBUG [main] - Returned connection 189219 to pool.
DEBUG [main] - Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.5
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Checked out connection 189219 from pool.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.Connection@2e323]
DEBUG [main] - ==>  Preparing: update user set username=?,birthday=?,sex=?,address=? where id=? 
DEBUG [main] - ==> Parameters: 张明明(String), 2015-06-07(Date), 男(String), 河南焦作(String), 1(Integer)
DEBUG [main] - <==    Updates: 1
DEBUG [main] - Committing JDBC Connection [com.mysql.jdbc.Connection@2e323]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.Connection@2e323]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.Connection@2e323]
DEBUG [main] - Returned connection 189219 to pool.
DEBUG [main] - Cache Hit Ratio [cn.edu.hpu.mybatis.mapper.UserMapper]: 0.3333333333333333
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Checked out connection 189219 from pool.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.Connection@2e323]
DEBUG [main] - ==>  Preparing: SELECT * FROM USER WHERE id=? 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
张明明
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.Connection@2e323]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.Connection@2e323]
DEBUG [main] - Returned connection 189219 to pool.
发现第二次再去查1号用户的时候,又再一次查询了数据库,查到了最新的数据"张明明"。

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

5.useCache配置

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

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

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

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

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


转载请注明出处:http://blog.csdn.net/acmman/article/details/46793289

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
10月前
|
存储 缓存 NoSQL
Redis专题-实战篇二-商户查询缓存
本文介绍了缓存的基本概念、应用场景及实现方式,涵盖Redis缓存设计、缓存更新策略、缓存穿透问题及其解决方案。重点讲解了缓存空对象与布隆过滤器的使用,并通过代码示例演示了商铺查询的缓存优化实践。
403 1
Redis专题-实战篇二-商户查询缓存
SQL XML Java
415 0
|
10月前
|
SQL Java 数据库连接
区分iBatis与MyBatis:两个Java数据库框架的比较
总结起来:虽然从技术角度看,iBATIS已经停止更新但仍然可用;然而考虑到长期项目健康度及未来可能需求变化情况下MYBATISS无疑会是一个更佳选择因其具备良好生命周期管理机制同时也因为社区力量背书确保问题修复新特征添加速度快捷有效.
862 12
|
10月前
|
SQL 缓存 监控
MySQL缓存机制:查询缓存与缓冲池优化
MySQL缓存机制是提升数据库性能的关键。本文深入解析了MySQL的缓存体系,包括已弃用的查询缓存和核心的InnoDB缓冲池,帮助理解缓存优化原理。通过合理配置,可显著提升数据库性能,甚至达到10倍以上的效果。
|
11月前
|
SQL XML Java
MyBatis框架如何处理字符串相等的判断条件。
总的来说,MyBatis框架提供了灵活而强大的机制来处理SQL语句中的字符串相等判断条件。无论是简单的等值判断,还是复杂的条件逻辑,MyBatis都能通过其标签和属性来实现,使得动态SQL的编写既安全又高效。
803 0
|
存储 缓存 NoSQL
Spring Cache缓存框架
Spring Cache是Spring体系下的标准化缓存框架,支持多种缓存(如Redis、EhCache、Caffeine),可独立或组合使用。其优势包括平滑迁移、注解与编程两种使用方式,以及高度解耦和灵活管理。通过动态代理实现缓存操作,适用于不同业务场景。
819 0
|
存储 缓存 NoSQL
mybatisplus一二级缓存
MyBatis-Plus 继承并优化了 MyBatis 的一级与二级缓存机制。一级缓存默认开启,作用于 SqlSession,适用于单次会话内的重复查询;二级缓存需手动开启,跨 SqlSession 共享,适合提升多用户并发性能。支持集成 Redis 等外部存储,增强缓存能力。
|
SQL XML Java
MyBatis Mapper中使用limit参数的查询问题
总结而言,MyBatis中使用 `limit`参数的查询可以高度定制并且灵活,基于方法签名和XML映射文件的组合来达成多样化的查询需求。通过参数化查询和动态SQL,MyBatis可以有效地处理各种复杂情境下的数据库操作,并且将SQL语句的维护与业务代码的编写相分离,提升代码的可维护性和可阅读性。
893 13
|
SQL Java 数据库
解决Java Spring Boot应用中MyBatis-Plus查询问题的策略。
保持技能更新是侦探的重要素质。定期回顾最佳实践和新技术。比如,定期查看MyBatis-Plus的更新和社区的最佳做法,这样才能不断提升查询效率和性能。
826 1
|
缓存 数据挖掘 BI