zoukankan      html  css  js  c++  java
  • 05、MyBatis 缓存

    1.MyBatis缓存

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

     

    1).一级缓存

    	public Employee getEmpById(Integer id);
    

      

    	<select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee" databaseId="mysql" >
    		select * from tbl_employee where id = #{id}
    	</select>
    

      

    	@Test
    	public void testFirstLevelCache() throws IOException {
    		SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
    		SqlSession openSession = sqlSessionFactory.openSession();
    		try {
    			
    			EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
    			Employee emp01 = mapper.getEmpById(10);
    			System.out.println(emp01);
    			
    			//
    			Employee emp02 = mapper.getEmpById(1-0);
    			System.out.println(emp02);
    			System.out.println(emp01==emp02);
    			
    		}finally {
    			openSession.close();
    		}
    	}

    2).一级缓存失效情况

    (1).sqlSession不同

    (2).sqlSession相同,查询条件不同(当前一级缓存中还没有这个数据)

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

    (4).sqlSession相同,手动清除了一级缓存

    	public Employee getEmpById(Integer id);
    

      

    	<select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee" databaseId="mysql" >
    		select * from tbl_employee where id = #{id}
    	</select>
    

      

    	@Test
    	public void testFirstLevelCache() throws IOException {
    		SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
    		SqlSession openSession = sqlSessionFactory.openSession();
    		try {
    			
    			EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
    			Employee emp01 = mapper.getEmpById(10);
    			System.out.println(emp01);
    			
    			//1、Sqlsession不同
    //			SqlSession openSession2 = sqlSessionFactory.openSession();
    //			EmployeeMapper mapper2 = openSession2.getMapper(EmployeeMapper.class);
    //			Employee emp02 = mapper2.getEmpById(10);
    			
    			//2、sqlSession相同,查询条件不同
    //			Employee emp02 = mapper.getEmpById(3);
    //			System.out.println(emp02);
    //			System.out.println(emp01==emp02);
    			
    			//3、sqlSession相同,两次查询之间执行了增删改操作
    //			mapper.addEmp(new Employee(null, "testCache", "cache@cache.com", "1"));
    //			System.out.println("数据添加成功");
    //			Employee emp02 = mapper.getEmpById(10);
    //			System.out.println(emp02);
    //			System.out.println(emp01==emp02);
    			
    			//4、sqlSession相同,手动清除了一级缓存
    			openSession.clearCache();
    			Employee emp02 = mapper.getEmpById(10);
    			System.out.println(emp02);
    			System.out.println(emp01==emp02);
    			
    		}finally {
    			openSession.close();
    		}
    	}
    

      

    3).二级缓存

      二级缓存(second level cache),全局作用域缓存.

      二级缓存默认不开启,需要手动配置.

      MyBatis提供二级缓存的接口以及实现,缓存实现要求POJO实现Serializable接口.

      二级缓存在 SqlSession 关闭或提交之后才会生效.

    (1).二级缓存使用

    二级缓存使用:

    ①.开启全局二级缓存配置:<setting name="cacheEnabled" value="true"/>

    ②.去需要使用二级缓存的xml中配置使用二级缓存;添加<cache></cache>

    ③.POJO需要实现序列化接口

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

      

    <mapper namespace="com.atguigu.mybatis.dao.EmployeeMapper">
    	<!-- cache:使用二级缓存的namespace -->
    	<!-- eviction:缓存的清除策略;LRU|FIFO|SOFT|WEAK -->
    		<!-- LRU – 最近最少使用的:移除最长时间不被使用的对象。 -->
    		<!-- FIFO – 先进先出:按对象进入缓存的顺序来移除它们。 -->
    		<!-- SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。 -->
    		<!-- WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。 -->
    	<!-- flushInterval(刷新间隔):缓存多长时间清空一次,默认不清空,可以设置一个毫秒值启用刷新间隔 -->
    	<!-- readOnly(只读):属性可以被设置为 true 或 false -->
    		<!-- true:只读;mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据; -->
    			<!-- 只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。 提供了可观的性能提升-->
    		<!-- false:非只读;mybatis觉得获取的数据可能会被修改; -->
    			<!-- 可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false -->
    	<!-- size(引用数目):属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源.默认值是 1024 -->
    	<!-- type:属性指定的类必须实现 org.apache.ibatis.cache.Cache 接口.且提供一个接受 String 参数作为 id 的构造器 -->
    		<!-- 指定自定义缓存的全类名,实现Cache接口即可 -->
    	<!-- <cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"></cache> -->
    	<cache></cache>
    </mapper>
    

      

    	@Test
    	public void testSecondLevelCache() throws IOException {
    		SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
    		SqlSession openSession = sqlSessionFactory.openSession();
    		SqlSession openSession2 = sqlSessionFactory.openSession();
    		try {
    			//1、
    			EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
    			EmployeeMapper mapper2 = openSession2.getMapper(EmployeeMapper.class);
    			
    			Employee emp01 = mapper.getEmpById(1);
    			System.out.println(emp01);
    			openSession.close();
    			
    			//第二次查询是从二级缓存中拿到的数据,并没有发送新的sql
    			//mapper2.addEmp(new Employee(null, "aaa", "nnn", "0"));
    			Employee emp02 = mapper2.getEmpById(1);
    			System.out.println(emp02);
    			openSession2.close();
    		}finally {
    			
    		}
    	}
    

      

    (2).二级缓存工作原理

    二级缓存工作原理:

    ①.一个会话,查询一条数,这个数据就会被放在当前会话的一级缓存中;

    ②.如果会话关闭;一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,就可以参照二级缓存中的内容;

    ③.不同namespace查出的数据会放在自己对应的缓存中(map):sqlSession===EmployeeMapper==>Employee|DepartmentMapper===>Department

    ④.二级缓存工作效果:查出的数据都会被默认先放在一级缓存中.只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中;

    (3).二级缓存属性设置

    ①.cacheEnabled="true|false": false关闭缓存(二级缓存关闭)(一级缓存一直可用的)

    ②.每个select标签都有useCache="true|false": false不使用缓存(一级缓存依然使用,二级缓存不使用)

    ③.*每个增删改标签的:flushCache="true|false":(一级二级都会清除)增删改执行完成后就会清楚缓存;

    测试:flushCache="true":一级缓存会被清空;二级也会被清空;每次查询之后都会清空缓存,缓存是没有被使用的;

    ④.sqlSession.clearCache();只是清除当前session的一级缓存

    ⑤.localCacheScope:本地缓存作用域;一级缓存SESSION;当前会话的所有数据保存在会话缓存中;STATEMENT:可以禁用一级缓存;

    /**

    * MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存

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

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

    * 以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库;

    * 一级缓存失效情况:没有使用到一级缓存的情况,效果就是两次查询都需要向数据库发出查询

    * 1sqlSession不同

    * 2sqlSession相同,查询条件不同(当前一级缓存中还没有这个数据)

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

    * 4sqlSession相同,手动清除了一级缓存

    *

    * 二级缓存(全局缓存):基于namespace级别的缓存;一个namespace对应一个二级缓存;

    * 二级缓存工作原理:

    * 1、一个会话,查询一条数,这个数据就会被放在当前会话的一级缓存中;

    * 2、如果会话关闭;一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,就可以参照二级缓存中的内容;

    * 3、不同namespace查出的数据会放在自己对应的缓存中(map):sqlSession===EmployeeMapper==>Employee|DepartmentMapper===>Department

    * 二级缓存工作效果:查出的数据都会被默认先放在一级缓存中.只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中;

    * 二级缓存使用:

    * 1、开启全局二级缓存配置:<setting name="cacheEnabled" value="true"/>

    * 2、去需要使用二级缓存的xml中配置使用二级缓存;添加<cache></cache>

    * 3POJO需要实现序列化接口

    *

    * 缓存有关属性/设置:

    * 1cacheEnabled="true|false": false关闭缓存(二级缓存关闭)(一级缓存一直可用的)

    * 2、每个select标签都有useCache="true|false": false不使用缓存(一级缓存依然使用,二级缓存不使用)

    * 3*每个增删改标签的:flushCache="true|false":(一级二级都会清除)增删改执行完成后就会清楚缓存;

    * 测试:flushCache="true":一级缓存会被清空;二级也会被清空;每次查询之后都会清空缓存,缓存是没有被使用的;

    * 4sqlSession.clearCache();只是清除当前session的一级缓存

    * 5localCacheScope:本地缓存作用域;一级缓存SESSION;当前会话的所有数据保存在会话缓存中;STATEMENT:可以禁用一级缓存;

    * @throws IOException

    */

    2.第三方缓存整合

      EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider.

      MyBatis定义了Cache接口方便我们进行自定义扩展. 

    参考文档:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html#cache

    http://mybatis.org/ehcache-cache/index.html

  • 相关阅读:
    heat模板
    Leetcode812.Largest Triangle Area最大三角形面积
    Leetcode812.Largest Triangle Area最大三角形面积
    Leetcode811.Subdomain Visit Count子域名访问计数
    Leetcode811.Subdomain Visit Count子域名访问计数
    Leetcode806.Number of Lines To Write String写字符串需要的行数
    Leetcode806.Number of Lines To Write String写字符串需要的行数
    Leetcode819.Most Common Word最常见的单词
    Leetcode819.Most Common Word最常见的单词
    Leetcode783.Minimum Distance Between BST Nodes二叉搜索树结点最小距离
  • 原文地址:https://www.cnblogs.com/CSAH/p/13152304.html
Copyright © 2011-2022 走看看