[] Buffer Mybatis

I. Overview

1.1 Cache meaning

  • Users often query the data in the cache (memory), users do not need to query data (relational database data files) from the disk query, the query from the cache to improve query efficiency, solve the problem of high-performance concurrent systems .

1.2 mybatis persistence cache

  • mybatis provide a cache and secondary cache

  • mybatis level cache is a SqlSession level, sqlsession only access their own data cache, secondary cache across sqlSession, a mapper level caching for mapper level caching different sqlsession it can be shared.

Second, the cache

2.1 Principle

  • The first issues a SQL query, the results of an SQL query sqlsession buffer write, the data structure is a map used by the cache
  • key: hashcode + sql + sql + input parameters an output parameter (the unique identification sql)
  • value: User Information
  • With a sqlsession make the same sql again, it does not take away from the cache database. If the middle appeared twice commit operation (modify, add, delete), a buffer area in this sqlsession all empty, go to the next cache can not find it from a database query, the query from the database to re-write cache.
  • Start every query cache query:
  • If the query cache to cache data will be returned directly.
  • If you can not find the cache from a database query:

2.2 cache configuration

  • mybatis default support level cache requires no configuration.
  • Note: After mybatis carried mapper agent development and integration of spring, do not support the cache, mybatis integration and spring, spring in accordance with the template mapper mapper to generate a proxy object, the template close sqlsession in the final reunification.

Cache test

//一级缓存
    @Test
    public void testCache1() throws Exception {

        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        
        //第一次查询用户id为1的用户
        User user = userMapper.findUserById(1);
        System.out.println(user);
        
        //中间修改用户要清空缓存,目的防止查询出脏数据
        /*user.setUsername("测试用户2");
        userMapper.updateUser(user);
        sqlSession.commit();*/
        
        //第二次查询用户id为1的用户
        User user2 = userMapper.findUserById(1);
        System.out.println(user2);
        
        sqlSession.close();
        

    }

Third, the secondary cache

3.1 Principle

  • 二级缓存的范围是mapper级别(mapper同一个命名空间),mapper以命名空间为单位创建缓存数据结构,结构是map
  • 每次查询先看是否开启二级缓存,如果开启从二级缓存的数据结构中取缓存数据,
  • 如果从二级缓存没有取到,再从一级缓存中找,如果一级缓存也没有,从数据库查询。

3.2 mybatis二级缓存配置

描述 允许值 默认值
cacheEnabled 对在此配置文件下的所有cache 进行全局性开/关设置。 true false true
  • 在核心配置文件SqlMapConfig.xml中加入
  • <setting name="cacheEnabled" value="true"/>
  • 要在你的Mapper映射文件中添加一行: ,表示此mapper开启二级缓存。

3.3 查询结果映射的pojo序列化

  • mybatis二级缓存需要将查询结果映射的pojo实现 java.io.serializable接口,如果不实现则抛出异常: org.apache.ibatis.cache.CacheException: Error serializing object. Cause: java.io.NotSerializableException: com.hao.mybatis.po.User
  • 二级缓存可以将内存的数据写到磁盘,存在对象的序列化和反序列化,所以要实现java.io.serializable接口。
  • 如果结果映射的pojo中还包括了pojo,都要实现java.io.serializable接口。

3.4 二级缓存禁用

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

3.5 刷新缓存

  • 如果sqlsession操作commit操作,对二级缓存进行刷新(全局清空)。
  • 设置statement的flushCache是否刷新缓存,默认值是true。

3.6 测试代码

@Test
    public void testCache2() throws Exception {

        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        SqlSession sqlSession3 = sqlSessionFactory.openSession();
        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
        UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);
        
        //第一次查询用户id为1的用户
        User user = userMapper1.findUserById(1);
        System.out.println(user);
        sqlSession1.close();
        
        //中间修改用户要清空缓存,目的防止查询出脏数据
        /*user.setUsername("测试用户2");
        userMapper3.updateUser(user);
        sqlSession3.commit();
        sqlSession3.close();*/
        
        
        //第二次查询用户id为1的用户
        User user2 = userMapper2.findUserById(1);
        System.out.println(user2);
        
        sqlSession2.close();
        

    }

3.7 mybatis的cache参数

  • mybatis的cache参数只适用于mybatis维护缓存。
  • flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
  • size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。
  • readOnly(只读)属性可以被设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。
  • 如下例子:
<cache  eviction="FIFO"  flushInterval="60000"  size="512"  readOnly="true"/>
  • 这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会导致冲突。可用的收回策略有, 默认的是 LRU:
  • LRU – 最近最少使用的:移除最长时间不被使用的对象。
  • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
  • SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
  • WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

3.8 二级缓存的应用场景

  • 对查询频率高,变化频率低的数据建议使用二级缓存。
  • 对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。
  • 实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。

3.9 mybatis局限性

  • mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。

Guess you like

Origin www.cnblogs.com/haoworld/p/mybatis-huan-cun.html