MyBatis二级缓存
Posted 旅行的Java
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis二级缓存相关的知识,希望对你有一定的参考价值。
配置二级缓存
Mybatis的一级缓存只存在于SqlSession的生命周期中,而二级缓存可理解为存在于SqlSessionFactory的生命周期中。虽然还没接触过同时存在多个SqlSessionFactory的情况,当存在多个SqlSessionFactory时,它们的缓存是绑定在各自的对象上的,缓存数据一般情况下是不想通的。只有在使用缓存服务器(如Redis),才可以共享缓存。
在Mybatis的全局配置settings中有一个参数cacheEnabled,这个参数时二级缓存的全局开关,默认是true,初始状态为启用状态。如果把这个参数设置为false,即使有后面的二级缓存配置,也不会生效。
Mybatis的二级缓存是和命名空间绑定的,即二级缓存需要配置在Mapper.xml映射文件中,或者配置在Mapper.java接口中
Mapper.xml中配置二级缓存
在保证二级缓存的全局配置开启的情况下,只需在mapper配置中添加<cache/>
元素即可。
1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
3"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
4<mapper namespace="com.aruisi.mybatis.mapper.UserMapper">
5 <!-- 开启二级缓存 -->
6 <cache/>
7 <select id="selectUserByNameAndSex" resultType="com.aruisi.mybatis.dto.UserDTO">
8 SELECT id,
9 login_name AS loginName,
10 sex,
11 age,
12 create_time AS createTime
13 FROM sys_user WHERE login_name=#{loginName} and sex=#{sex}
14 </select>
15</mapper>
二级缓存的默认配置
1.映射文件中的所有select语句将会被缓存;
2.映射文件中的所有INSERT、UPDATE、DELETE语句会刷新缓存;
3.缓存会使用LRU(最近最少使用)算法来回收;
4.根据时间表(如no Flush Interval,没有刷新间隔),缓存不会以任何时间顺序来刷新;
5.缓存会存储集合或对象(无论查询方法返回什么类型的值)的1024个引用;
6.缓存会被视为read/write。
所有这些配置都可通过缓存元素的属性来修改
1<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
2这段配置创建了一个FIFO缓存,并每隔60s刷新一次,存储512个引用,返回的对象时只读的。
eviction(收回策略)
1.LRU – 最近最少使用的:移除最长时间不被使用的对象。
2.FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
3.SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
4.WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
flushInterval(刷新间隔)
可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
size(引用数目)
可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。readOnly(只读)属性可以被设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。 这会慢一些,但是安全,因此默认是false。
二级缓存使用
测试代码
1public class TestCache {
2 public static void main(String[] args) throws IOException {
3 //读取配置文件信息
4 Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
5 SqlSessionFactory build = new SqlSessionFactoryBuilder().build(reader);
6
7 //参数为true,设置事务是自动提交
8 SqlSession sqlSession0 = build.openSession(true);
9 SysUserDAO userMapper = sqlSession0.getMapper(SysUserDAO.class);
10 //第一次查询
11 SysUserEntity aDTO = userMapper.selectByPrimaryKey("40288ab85ce3c20a015ce3ca6df60000");
12 System.out.println("第一次查询==="+aDTO.toString());
13 //重新设置用户的姓名
14 aDTO.setRealname("zmk");
15 //第二次查询
16 SysUserEntity sysUser = userMapper.selectByPrimaryKey("40288ab85ce3c20a015ce3ca6df60000");
17 System.out.println("第二次查询==="+sysUser.toString());
18 sqlSession0.close();
19
20 System.out.println("----------------------------开启一个新的session-------------------------------");
21
22 //参数为true,设置事务是自动提交
23 SqlSession sqlSession1 = build.openSession(true);
24 SysUserDAO userMapper1 = sqlSession1.getMapper(SysUserDAO.class);
25 //第一次查询
26 SysUserEntity aDTO1 = userMapper1.selectByPrimaryKey("40288ab85ce3c20a015ce3ca6df60000");
27 System.out.println("开启新的session后的第一次查询==="+aDTO1.toString());
28
29 //第二次查询
30 SysUserEntity sysUser1 = userMapper1.selectByPrimaryKey("40288ab85ce3c20a015ce3ca6df60000");
31 System.out.println("开启新的session后的第二次查询==="+sysUser1.toString());
32
33 sqlSession1.close();
34 }
35}
运行结果
第一次查询没有缓存,缓存命中率是0,查询了数据库,第二次查询,没有查询数据库,并且查询到的realName=“zmk”,这是用到了一级缓存。当close掉SqlSession时,SqlSession才会保存查询数据到二级缓存,所以第一部分的2次查询命中率都是0。当开启一个新的session后,再次查询时,输出的命中率为0.3(1/3),第二次查询时,就变成0.5,查询了4次,2次命中。
以上是关于MyBatis二级缓存的主要内容,如果未能解决你的问题,请参考以下文章