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二级缓存的主要内容,如果未能解决你的问题,请参考以下文章

mybatis二级缓存详解

Mybatis缓存

MyBatis系列目录--5. MyBatis一级缓存和二级缓存(redis实现)

真正的mybatis_redis二级缓存

使用Redis做MyBatis的二级缓存

mybatis二级缓存默认开启吗?