zoukankan      html  css  js  c++  java
  • Mybatis缓存机制

    Mybatis系统中默认定义了两级缓存。

    一级缓存二级缓存

    1、默认情况下只有一级缓存(SqlSession级别的缓存,也称为本地缓存)开启

    2、二级缓存需要手动开启和配置,它是基于namespace级别的缓存

    3、为了提高扩展性。Mybatis定义了缓存借口Cache,我们可以通过实现Cache借口来自定义二级缓存

    一级缓存

    一级缓存:(本地缓存):sqlSession级别的缓存,一级缓存是一直开启的;SqlSession级别的一个Map
         *          与数据库同一次会话期间查询到的数据会放在本地缓存中
         *          以后如果需要获取相同的数据,直接从缓存中获取,没必要再去从查询数据库
         *
         *          一级缓存失效情况(没有使用到当前一级缓存的情况,结果就是还需要向数据库发出查询)
         *          1、sqlSession不同
         *          2、sqlSession相同,但是查询条件不同(当前一级缓存中还没有这个数据)
         *          3、sqlSession相同,但是两次查询之间实现了增删改操作(这次增删改可能对当前操作有影响)

         *          4、sqlSession相同,但是认为手动清除了一级缓存

    二级缓存

    二级缓存:(全局缓存):基于namespace级别的缓存;一个namespace对应一个二级缓存
         *          工作机制:
         *          1、一个会话:查询一条数据,这个数据就会被放在当前会话的一级缓存中
         *          2、如果会话关闭(一级缓存没有了),一级缓存中的数据会被保存到二级缓存中,
         *          新的会话查询信息就可以参照二级缓存中的内容
         *          3、sqlSession===》EmployeeMapper===》Employee
         *                            DepartmentMapper===》Department
         *               不同的namespace查出的数据会被放在自己对应的缓存中(map)
         *               使用:
         *               1、在全局配置文件中开启全局二级缓存配置: <setting name="cacheEnabled" value="true"/>
         *               2、去mapper.xml映射文件中配置
         *               3、我们的POJO需要实现序列化接口

    <setting name="cacheEnabled" value="true"/>
    <mapper namespace="dao.EmployeeMapper">
        <cache eviction="FIFO" flushInterval="6000" readOnly="false" size="1024"></cache>
            <!--
            eviction:缓存的回收策略
                 ※LRU:最近最少使用的:移除最长时间不被使用的对象(默认使用)
                 ※FIFO:先进先出:按对象进入缓存的顺序来移除他们
                 ※SOFT:软引用:移除基于垃圾回收器状态和软引用规则的对象
                 ※WEAK:弱引用:更积极的移除基于垃圾回收器状态和弱引用规则的对象
            flushInterval:刷新间隔
                缓存多长时间清空一次,默认不清空,设置一个毫秒值
            readOnly:是否只读
                    true:只读:mybatis认为所有缓存中获取数据的操作都是只读操作,不会修改数据
                                mybatis为了加快获取速度,直接就会将数据在缓存中的引用交给用户。不安全,但是速度块
                    false:非只读:mybatis觉得获取数据会被修改
                                  mybatis会利用序列化&反序列化的技术克隆一份新的数据给你。安全、速度慢
            size:缓存存放多少元素
            type:指定自定义缓存的全类名——实现Cache接口即可
            -->
        <sql id="emp">
          id,last_name,email,gender
        </sql>
        <resultMap id="emp" type="bean.Employee">
            <id column="id" property="id"/>
            <result column="last_name" property="lastName"/>
            <result column="email" property="email"/>
            <result column="gender" property="gender"/>
        </resultMap>
        <select id="getEmps" resultMap="emp">
            SELECT
            <include refid="emp"></include>
            FROM t_employee
            <where>
                <if test="id!=null">
                    id=#{id}
                </if>
            </where>
        </select>
    </mapper>

    最开始测试的时候:

    public SqlSession getSqlSession() throws IOException {
        String str = "mybatis-config.xml";
        Reader reader = Resources.getResourceAsReader(str);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        return sqlSession;
    }
    @Test
    public void testSecondLevelCache() throws IOException {
        SqlSession sqlSession1 = getSqlSession();
        SqlSession sqlSession2 =getSqlSession();
        try {
            EmployeeMapper mapper1 = sqlSession1.getMapper(EmployeeMapper.class);
            EmployeeMapper mapper2 = sqlSession2.getMapper(EmployeeMapper.class);
    
            Employee e1=mapper1.getEmps(1);
            System.out.println(e1);
            sqlSession1.close();
            //二次查询是从二级缓存中拿到数据,并没与发送新的sql
            Employee e2=mapper2.getEmps(1);
            System.out.println(e2);
            sqlSession2.close();
    
        } finally {
    
        }
    
    }

    直接调用了getSqlSession方法,创建了两次SqlSessionFactory对象,结果:


    开启二级缓存失败了

    查阅资料改为:

    @Test
    public void testSecondLevelCache() throws IOException {
        String str = "mybatis-config.xml";
        Reader reader = Resources.getResourceAsReader(str);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
    
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 =sqlSessionFactory.openSession();
          
       /* SqlSession sqlSession1 = getSqlSession();
        SqlSession sqlSession2 =getSqlSession();*/
        try {
            EmployeeMapper mapper1 = sqlSession1.getMapper(EmployeeMapper.class);
            EmployeeMapper mapper2 = sqlSession2.getMapper(EmployeeMapper.class);
    
            Employee e1=mapper1.getEmps(1);
            System.out.println(e1);
            sqlSession1.close();
            //二次查询是从二级缓存中拿到数据,并没与发送新的sql
            Employee e2=mapper2.getEmps(1);
            System.out.println(e2);
            sqlSession2.close();
    
        } finally {
    
        }
    
    }

    两次获得SqlSession对象只创建了一次SqlSessionFactory,开启二级缓存ok



    和缓存有关的设置和属性

    1)cacheEnabled=true开启缓存;false关闭缓存(关闭的是二级缓存,一级缓存可用不受影响)

    2)每个select标签都会有useCache="true"属性,

            false:不使用缓存(一级缓存不受影响,二级缓存不可用)

    3)每个增删改的 flushCache="true"默认,(一级二级都会清除)
         *          ——增删改执行完成之后就会清除缓存
         *          测试:flushCache="true",就会清空一级缓存,二级缓存也会被清空
         *          查询标签默认:flushCache="false",如果改为true则每次查询之后都会清理缓存,所以缓存是没有被使用的
     4)SqlSession.clearCache( );只清除当前session的一级缓存,对二级缓存没影响

     5)localCacheScope:本地缓存作用域(一级缓存)

                                        SESSION:当前回话的所有数据保存在会话缓存中

                                        STATEMENT:可以禁用一级缓存

    缓存原理图:




  • 相关阅读:
    HDU 5835 Danganronpa 贪心
    HDU 5842 Lweb and String 水题
    HDU 5832 A water problem 水题
    Codeforces Beta Round #14 (Div. 2) A. Letter 水题
    Western Subregional of NEERC, Minsk, Wednesday, November 4, 2015 Problem K. UTF-8 Decoder 模拟题
    Western Subregional of NEERC, Minsk, Wednesday, November 4, 2015 Problem I. Alien Rectangles 数学
    Western Subregional of NEERC, Minsk, Wednesday, November 4, 2015 Problem H. Parallel Worlds 计算几何
    Western Subregional of NEERC, Minsk, Wednesday, November 4, 2015 Problem F. Turning Grille 暴力
    Western Subregional of NEERC, Minsk, Wednesday, November 4, 2015 Problem C. Cargo Transportation 暴力
    Western Subregional of NEERC, Minsk, Wednesday, November 4, 2015 Problem G. k-palindrome dp
  • 原文地址:https://www.cnblogs.com/huangzhe1515023110/p/9276081.html
Copyright © 2011-2022 走看看