04_Mybatis_缓存

缓存_缓存介绍

  • MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便的配置和定制。缓存可以极大的提升查询效率

  • MyBatis系统中 默认定义了两级缓存

  • 一级缓存和二级缓存

    • 1、默认情况下:只有一级缓存(SqlSession级别的缓存,也称为本地缓存)开启;
    • 2、二级缓存需要手动开启和配置,他是基于namespace级别的缓存
    • 3、为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存

缓存_一级缓存体验

两级缓存

​ 一级缓存:(本地缓存)sqlSession级别的缓存。一级缓存是一直开启的;SqlSession级别的Map

​ 与数据库同一次会话期间查询到的数据会放在本地缓存中。

​ 如果再次获取相同的数据,直接从缓存中拿。

​ 二级缓存:(全局缓存)

缓存_一级缓存失效的四种情况

一级缓存失效情况(没有使用到当前一级缓存的情况,效果就是,还要再次向数据库发送sql)

1、sqlSession不同

2、sqlSession相同,查询条件不同

3、sqlSession相同,两次查询之间执行增删改操作(这次增删改操作可能影响当前数据)

4、sqlSession相同,手动清除一级缓存(缓存情况)openSession.clearCache();

@Test
    public  void testFirstLevelCache() throws IOException {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession openSession = sqlSessionFactory.openSession();
        try {
            //一级缓存初体验
            EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
            Employee empById01 = mapper.getEmpById(1);
            System.out.println(empById01);

            //1、sqlSession不同。
            /*SqlSession openSession2 = sqlSessionFactory.openSession();
            EmployeeMapper mapper2 = openSession2.getMapper(EmployeeMapper.class);*/

            //3、sqlSession相同,两次查询之间执行了增删改操作;(增删改操作有可能影响当前数据)
            /*mapper.addEmp(new Employee(null,"cache","1","testCache@qq.com"));
            System.out.println("数据添加成功");*/

            //4、sqlSession相同,手动清空一级缓存
            // openSession.clearCache();

            //2、sqlSession相同,查询条件不同
            Employee empById02 = mapper.getEmpById(1);
            System.out.println(empById02);
            System.out.println(empById01 == empById02);

            // openSession2.close();

        } finally {
            openSession.close();
        }
    }

缓存_二级缓存使用&细节

1、开启全局二级缓存配置

<setting name="cacheEnabled" value="true"></setting>

2、去mapper.xml中配置使用二级缓存

	<cache eviction="" flushInterval="" readOnly="" size="" type=""></cache>
	<!--
		eviction:缓存回收策略
			· LRU:最近使用最少的,移除最长时间不被使用的对象
			· FIFO:先进先出,按对象进入缓存的顺序来移除
			· SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象
			· WEAK:弱引用,更积极的移除垃圾回收器状态和弱引用规则的对象
			· 默认是LRU

		flushInterval:刷新间隔,单位毫秒
			· 默认情况下是不设置,没有刷新时间,缓存仅仅调用语句时刷新

		size:引用数目,正整数
			· 代表缓存最大可以存储多少个对象,太大容易导致内存溢出

		readOnly:只读,true/false
			· true:只读缓存,会给所有调用者返回缓存对象的相同实例
			1 false:读写缓存,会返回缓存对象的拷贝(通过序列化),
		type:指定自定义缓存的全类名;
                实现Cache接口即可
	-->
/**
*两级缓存:
     *  一级缓存(本地缓存):sqlSession级别的缓存,一级缓存是一直开启的,sqlSession级别的一个Map
     *      与数据库同一次会话期间查询到的数据会放在本地缓存中。
     *
     *      一级缓存失效情况(没有使用到当前一级缓存的情况):
     *          1、sqlSession不同。
     *          2、sqlSession相同,查询条件不同(当前一级缓存中还没有这个数据)
     *          3、sqlSession相同,两次查询之间执行了增删改操作;(增删改操作有可能影响当前数据)
     *          4、sqlSession相同,手动清空一级缓存
     *
     *  二级缓存(全局缓存):基于namespace级别的缓存,一个namespace对应一个二级缓存;
     *      工作机制:
     *          1、一次会话,查询一条数据,这个数据就会被放在当前会话的一级缓存中
     *          2、如果会话关闭,一级缓存中的数据会被保存到二级缓存中。新的会话查询信息,就可以参照二级缓存
     *          3、不同的namespace查出的数据会放在自己对应的缓存中(namespace级别的map)
     *
     *              查出的数据都会默认先放在一级缓存中,
     *                  只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存
     *  使用&细节:
     *          1)、开启全局二级缓存配置.<setting name="cacheEnabled" value="true"/>
     *          2)、去mapper.xml中配置使用二级缓存;<cache></cache>
     *          3)、POJO需要实现序列化接口
     */
@Test
    public void testSecondLevelCache() throws IOException {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession openSession = sqlSessionFactory.openSession();
        SqlSession openSession2 = sqlSessionFactory.openSession();
        try {
            //
            EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
            EmployeeMapper mapper2 = openSession2.getMapper(EmployeeMapper.class);

            Employee emp01 = mapper.getEmpById(1);
            System.out.println(emp01);
            openSession.close();

            //第二次查询是从二级缓存中拿到的数据
            Employee emp02 = mapper2.getEmpById(1);
            System.out.println(emp02);
            openSession2.close();
        } finally {
            // openSession.close();
        }
    }

缓存_缓存有关的配置以及属性

/**
	 *  和缓存有关的设置/属性
     *          1)、cacheEnabled=true,【false:关闭缓存(二级缓存关闭,不会关闭一级缓存)】
     *          2)、每个select标签都有一个useCache标签,useCache="true"
     *              false:不使用缓存【一级缓存仍然可以使用,二级缓存不使用】
     *          3)、每个增删改标签都有flushCache标签,flushCache="true"【一级二级都会清除】
     *              增删改执行后就会清除缓存
     *              测试:flushCache="true",一级缓存清空了,二级缓存也会被清除
     *              查询标签也有flushCache="true"
     *                  如果设置为false,每次查询之后都会清空缓存,缓存不会被使用
     *          4)、openSession.clearCache();只是清除当前session的一级缓存
     *          5)、localCacheScope:本地缓存作用域(一级缓存SESSION),当前会话的所有数据保存在会话缓存中。
     *                  若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。【禁用一级缓存】
     * */

缓存_缓存原理图示

posted @ 2020-10-24 13:08  san只松鼠  阅读(98)  评论(0)    收藏  举报