mybatis进阶(8)--查询缓存之二级缓存
来源:互联网 发布:android源码语法 编辑:程序博客网 时间:2024/05/15 23:45
话不多说看图:
上节中提到,二级缓存是mapper级别的。可以跨sqlSession使用。
过程分析:
首先我们需要手动开启mybatis的二级缓存
sqlSession1发起查询用户id为1的用户信息,先去缓存中后是否有id为1的用户信息,如果没有,从数据库查询用户信息,并将用户信息存储到二级缓存中去
如果sqlSession3去执行相同mapper下的commit操作(插入,更新,删除),清空sqlSession的二级缓存
sqlSession2发起查询用户id为1的用户信息,先去缓存中后是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。
二级缓存和一级缓存的区别:
二级缓存的范围更大,多个sqlSession共享一个userMapper的二级缓存
userMapper有一个二级缓存区域(按namespace分),其他的mapper也有自己的二级缓存区域
每个namespace的mapper都有一个二级缓存区域,两个mapper的namespace如果相同,那么这两个mapper执行sql查询将数据存在相同的二级缓存中去
1.开启二级缓存:
二级缓存是mapper范围级别,除了在sqlMapConfig.xml中配置二级缓存开关,还需要在具体的mapper.xml中开启二级缓存
在sqlMapConfig.xml中的settings中配置
<settings> <!-- 打开延迟加载开关 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 将积极加载改变成消极加载,也就是需要时加载 --> <setting name="aggressiveLazyLoading" value="false"/> <!-- 开启二级缓存 --> <setting name="cacheEnabled" value="true"/> </settings>
在userMapper.xml中开启二级缓存,它里面的sql执行完会存储到它的缓存区域(hashmap)中
<!-- 开启本mapper的namespace下的二级缓存 --> <cache></cache>
2.调用pojo类的实现序列化接口
public class User implements Serializable{...}
为了将缓存数据去除执行反序列化,因为为二级缓存数据存储介质不一样
3.测试二级缓存
先来测试下两次请求查询的执行结果
// 测试二级缓存 @Test public void testCache2() throws Exception { SqlSession sqlSession1 = sqlSessionFactory.openSession(); SqlSession sqlSession2 = sqlSessionFactory.openSession(); SqlSession sqlSession3 = sqlSessionFactory.openSession(); // 获取代理对象 UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class); // 使用sqlSession1 // 第一次发起请求查询用户id为1的用户 User u = userMapper1.findUserById(1); System.out.println(u); // 这里执行关闭操作,将sqlSession1中的数据写到二级缓存 sqlSession1.close(); UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class); // 使用sqlSession2 // 第2次发起请求查询用户id为1的用户 User u2 = userMapper2.findUserById(1); System.out.println(u2); sqlSession2.close(); }
执行结果:
Cache Hit Ratio [com.ddd.mybatis.mapper.UserMapper]: 0.02017-07-19 08:54:19,761 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection2017-07-19 08:54:20,006 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 762493988.2017-07-19 08:54:20,006 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@2d72bc24]2017-07-19 08:54:20,008 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] ==> Preparing: SELECT * FROM USER WHERE id=? 2017-07-19 08:54:20,074 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] ==> Parameters: 1(Integer)2017-07-19 08:54:20,100 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] <== Total: 1User [id=1, username=林更新, sex=男, birthday=Tue Jul 18 00:00:00 CST 2017, address=北京市海淀区, ordersList=null]2017-07-19 08:54:20,111 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@2d72bc24]2017-07-19 08:54:20,112 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@2d72bc24]2017-07-19 08:54:20,113 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Returned connection 762493988 to pool.2017-07-19 08:54:20,134 [main] [com.ddd.mybatis.mapper.UserMapper]-[DEBUG] Cache Hit Ratio [com.ddd.mybatis.mapper.UserMapper]: 0.5User [id=1, username=林更新, sex=男, birthday=Tue Jul 18 00:00:00 CST 2017, address=北京市海淀区, ordersList=null]
可以看出来,Cache Hit Ratio [com.ddd.mybatis.mapper.UserMapper]: 0.0表示缓存命中率为0,因为第一次在缓存中没有找到,所以去数据库中找,发出了sql语句,第二次找就直接在缓存中找,然后命中,两次找到一次,所以命中率为0.5
再来测试3个有查询有提交的:
// 测试二级缓存 @Test public void testCache2() throws Exception { SqlSession sqlSession1 = sqlSessionFactory.openSession(); SqlSession sqlSession2 = sqlSessionFactory.openSession(); SqlSession sqlSession3 = sqlSessionFactory.openSession(); // 获取代理对象 UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class); // 使用sqlSession1 // 第一次发起请求查询用户id为1的用户 User u = userMapper1.findUserById(1); System.out.println(u); // 这里执行关闭操作,将sqlSession1中的数据写到二级缓存 sqlSession1.close(); // 获取代理对象 UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class); // 使用sqlSession3 // 第2次发起请求查询用户id为1的用户 User u3 = userMapper3.findUserById(1); u3.setUsername("王思聪"); userMapper3.updateUser(u3); sqlSession3.commit(); System.out.println(u3); // 这里执行关闭操作,将sqlSession3中的数据写到二级缓存 sqlSession3.close(); UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class); // 使用sqlSession2 // 第3次发起请求查询用户id为1的用户 User u2 = userMapper2.findUserById(1); System.out.println(u2); sqlSession2.close(); }
Cache Hit Ratio [com.ddd.mybatis.mapper.UserMapper]: 0.02017-07-19 09:01:15,731 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection2017-07-19 09:01:15,983 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 1019014919.2017-07-19 09:01:15,983 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3cbcef07]2017-07-19 09:01:15,986 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] ==> Preparing: SELECT * FROM USER WHERE id=? 2017-07-19 09:01:16,042 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] ==> Parameters: 1(Integer)2017-07-19 09:01:16,064 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] <== Total: 1User [id=1, username=林更新, sex=男, birthday=Tue Jul 18 00:00:00 CST 2017, address=北京市海淀区, ordersList=null]2017-07-19 09:01:16,072 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3cbcef07]2017-07-19 09:01:16,072 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3cbcef07]2017-07-19 09:01:16,072 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Returned connection 1019014919 to pool.2017-07-19 09:01:16,075 [main] [com.ddd.mybatis.mapper.UserMapper]-[DEBUG] Cache Hit Ratio [com.ddd.mybatis.mapper.UserMapper]: 0.52017-07-19 09:01:16,075 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection2017-07-19 09:01:16,075 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Checked out connection 1019014919 from pool.2017-07-19 09:01:16,076 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3cbcef07]2017-07-19 09:01:16,076 [main] [com.ddd.mybatis.mapper.UserMapper.updateUser]-[DEBUG] ==> Preparing: UPDATE USER SET username=?,birthday=?,sex=?,address=? WHERE id=? 2017-07-19 09:01:16,079 [main] [com.ddd.mybatis.mapper.UserMapper.updateUser]-[DEBUG] ==> Parameters: 王思聪(String), 2017-07-18 00:00:00.0(Timestamp), 男(String), 北京市海淀区(String), 1(Integer)2017-07-19 09:01:16,080 [main] [com.ddd.mybatis.mapper.UserMapper.updateUser]-[DEBUG] <== Updates: 12017-07-19 09:01:16,080 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3cbcef07]User [id=1, username=王思聪, sex=男, birthday=Tue Jul 18 00:00:00 CST 2017, address=北京市海淀区, ordersList=null]2017-07-19 09:01:16,140 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3cbcef07]2017-07-19 09:01:16,141 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3cbcef07]2017-07-19 09:01:16,141 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Returned connection 1019014919 to pool.2017-07-19 09:01:16,141 [main] [com.ddd.mybatis.mapper.UserMapper]-[DEBUG] Cache Hit Ratio [com.ddd.mybatis.mapper.UserMapper]: 0.33333333333333332017-07-19 09:01:16,141 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection2017-07-19 09:01:16,141 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Checked out connection 1019014919 from pool.2017-07-19 09:01:16,142 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3cbcef07]2017-07-19 09:01:16,142 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] ==> Preparing: SELECT * FROM USER WHERE id=? 2017-07-19 09:01:16,143 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] ==> Parameters: 1(Integer)2017-07-19 09:01:16,145 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] <== Total: 1User [id=1, username=王思聪, sex=男, birthday=Tue Jul 18 00:00:00 CST 2017, address=北京市海淀区, ordersList=null]
当sqlSession3提交后,将会清空二级缓存,下次查将查最新的数据,所以第三次查询会发出sql代码
4.禁用二级缓存
在statement中设置useCache=”false”将会禁用二级缓存,每次查询都会发出sql去查询,默认是true,即该sql使用二级缓存
应用场合:针对每次查询都需要最新数据sql,要设置禁用二级缓存
5.刷新缓存(就是清空缓存)
在同一namespace下的mapper中,如果有增删改操作后需要刷新缓存,避免脏读
在statement中设置flushCache=”false”将会不刷新缓存,他默认是true。如果设置为false,在我们手动更改数据库中的查询数据会出现脏读
一般执行完commit操作都要执行刷新缓存,防止脏读数据。
- mybatis进阶(8)--查询缓存之二级缓存
- 【Mybatis框架】查询缓存(二级缓存)
- MyBatis之缓存(一级缓存、二级缓存)
- mybatis进阶(7)--查询缓存之一级缓存
- MyBatis--查询缓存--内置二级缓存
- Mybatis - 查询缓存(一级缓存,二级缓存,与ehcache整合)
- 【MyBatis】查询缓存(一级缓存和二级缓存)
- mybatis学习笔记(15)-查询缓存之二级缓存
- Mybatis学习笔记(十六)【查询缓存之二级缓存】
- MyBatis缓存策略之二级缓存
- 【MyBatis框架】查询缓存-二级缓存原理
- 【MyBatis框架】查询缓存-二级缓存-整合ehcache
- 【MyBatis框架】查询缓存-二级缓存原理
- 【MyBatis框架】查询缓存-二级缓存-整合ehcache
- MyBatis--查询缓存--内置二级缓存配置
- MyBatis--查询缓存--关闭内置二级缓存
- MyBatis--查询缓存--ehcache二级缓存配置
- MyBatis--查询缓存--ehcache二级缓存配置文件详解
- 回调函数
- 虚拟机如何实现的?
- 敏捷开发 —— TDD(测试驱动开发)
- linux debian配置静态IP,网关,DNS详细步骤
- js 创建对象的方式
- mybatis进阶(8)--查询缓存之二级缓存
- 数据结构——栈(C++实现)
- 使用dom4j实现读取和写入xml文件
- let关键字
- 在移动端输入框在软键盘弹出后位置矫正
- bzoj4199[luoguP2178]品酒大会[noi2015] (后缀数组+并查集)
- SNMP实践
- 没有Bug的二分法
- linux debian8.2版本安装详细步骤(无图)