zoukankan      html  css  js  c++  java
  • mybatis0209 二级缓存

    1.1二级缓存
    1.1.1原理
    mybatis和spring整合后一级缓存就没有了,sqlSession在不关闭的前提下2次查询就会从缓存中取,一级缓存缓存在sqlSession对象里面,当多用户查询的时候就用到二级缓存了。UserMapper缓存:会把根据id和根据name查询的用户信息写进缓存,如果有人发了insert语句则会把所有的用户信息清空,二级缓存是命名空间级别的。

    二级缓存的范围是mapper级别(mapper同一个命名空间的缓存,在UserMapper.xml里面有一个命名空间<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">,不同的xml文件中命名空间可以相同),mapper以命名空间为单位创建缓存数据结构,结构是map<key、value>。
    每次查询先看是否开启二级缓存,如果开启从二级缓存的数据结构中取缓存数据,

    如果从二级缓存没有取到,再从一级缓存中找,如果一级缓存也没有,从数据库查询。
    1.1.1mybatis二级缓存配置
    在核心配置文件SqlMapConfig.xml中加入
    <setting name="cacheEnabled" value="true"/>

    描述

    允许值

    默认值

    cacheEnabled

    对在此配置文件下的所有cache 进行全局性开/关设置。

    true false

    true

    要在你的Mapper映射文件中添加一行:  <cache /> ,表示此mapper开启二级缓存。
    1.1.1查询结果映射的pojo序列化
    mybatis二级缓存需要将查询结果映射的pojo实现 java.io.serializable接口,如果不实现则抛出异常:
    org.apache.ibatis.cache.CacheException: Error serializing object.  Cause: java.io.NotSerializableException: cn.itcast.mybatis.po.User
    因为二级缓存可以将内存的数据写到磁盘,存在对象的序列化和反序列化,所以要实现java.io.serializable接口。
    如果结果映射的pojo中还包括了pojo,都要实现java.io.serializable接口。
    1.1.1二级缓存禁用
    对于变化频率较高的sql(比如支付宝银行账户余额),存到缓存没有意义因为一直在变化,需要禁用二级缓存:
    在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。
    <select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">
    1.1.2刷新缓存
    如果sqlsession操作commit操作,对二级缓存进行刷新(全局清空)。
    设置statement的flushCache是否刷新缓存,默认值是true,默认建议刷新,如果不刷新就会读取脏数据。把select中的 useCache="false"去掉,在insert或update中<update id="updateUser" parameterType="cn.itcast.mybatis.po.User" flushCache="false">加上flushCache="false"
    1.1.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);
            UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
            UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);
            
            //第一次查询用户id为1的用户,此时会写入缓存,如果设置刷新间隔为1秒,那么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();
    1.1.1mybatis的cache参数(了解)
    mybatis的cache参数只适用于mybatis维护缓存。
    flushInterval(刷新间隔,过了这个时间缓存就清空了)可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
    size(引用数目,缓存对象的个数)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。
    readOnly(只读)属性可以被设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。
    eviction="FIFO" 表示缓存策略,比如到达时间后如何清空,清空的方案,
    如下例子:
    <cache  eviction="FIFO"  flushInterval="60000"  size="512"  readOnly="true"/>
    这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会导致冲突。可用的收回策略有, 默认的是 LRU:
    1.LRU – 最近最少使用的:移除最长时间不被使用的对象。
    2.FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
    3.SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
    4.WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
  • 相关阅读:
    Docker 中 MySql 启动失败,报错 Can't open and lock privilege tables: Table storage engine for 'user'
    使用命令行编译和运行Java代码
    Linux编程--进程间通信
    Linux编程--信号
    HDU 2159 完全背包
    HDU 2844 多重背包
    hdu 2602 dp 01背包
    hdu 1864 01背包
    JSON学习
    Django Cookie
  • 原文地址:https://www.cnblogs.com/yaowen/p/5203440.html
Copyright © 2011-2022 走看看