05、MyBatis 缓存

1.MyBatis缓存

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

 05、MyBatis 缓存_第1张图片

1).一级缓存

	public Employee getEmpById(Integer id);

  

	

  

	@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);

  

	

  

	@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", "[email protected]", "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).二级缓存使用

二级缓存使用:

①.开启全局二级缓存配置:

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

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

		

  


	
	
		
		
		
		
	
	
		
			
		
			
	
	
		
	
	

  

	@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、开启全局二级缓存配置:

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

* 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

你可能感兴趣的:(05、MyBatis 缓存)