Mybatis 框架总结(五) :缓存机制

正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持

1.一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。Session.clearCache()

2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。

3. 对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。

一级缓存

现在进行一级缓存的测试

package sdibt.lxj.test;

import org.apache.ibatis.session.SqlSession;
import sdibt.lxj.dao.IBookDao;
import sdibt.lxj.util.MybatisUtils;

public class TestMybatisCache {
	public static void main(String[] args) throws ClassNotFoundException {
		SqlSession session = MybatisUtils.getSession();		
		IBookDao dao = session.getMapper(IBookDao.class);			
		//发出两条查询语句
		System.out.println("进行第一次查询");
		 dao.all();			 
		 System.out.println("进行第二次查询");
		 dao.all();			
	}
}

测试结果,很明显,在进行第二次查询的时候已经将该查询缓存了起来,不再执行sql,也就是说Mybatis默认是开启一级缓存的,不过必须是同一个session才有效

2018-07-08 15:50:42  [ main:0 ] - [ INFO ]  {dataSource-1} inited
2018-07-08 15:50:42  [ main:54 ] - [ DEBUG ]  Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
进行第一次查询
2018-07-08 15:50:42  [ main:80 ] - [ DEBUG ]  Opening JDBC Connection
2018-07-08 15:50:42  [ main:82 ] - [ DEBUG ]  Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@9a7504c]
2018-07-08 15:50:42  [ main:90 ] - [ DEBUG ]  ==>  Preparing: select * from book 
2018-07-08 15:50:42  [ main:139 ] - [ DEBUG ]  ==> Parameters: 
2018-07-08 15:50:42  [ main:165 ] - [ DEBUG ]  <==      Total: 7
进行第二次查询

在查询完一次加上session.clearCache();就把session内的缓存清空了

System.out.println("进行第一次查询");
		 dao.all();			 
		 session.clearCache();
		 System.out.println("进行第二次查询");
		 dao.all();	

在测试一下如果对表内的数据进行修改的话,缓存的查询会不会存在

//发出两条查询语句
		System.out.println("进行第一次查询");
		 dao.all();			 
		//删除一条记录
		 dao.delete1(7);		 
		 System.out.println("进行第二次查询");
		 dao.all();

看来对表进行修改会破坏一级缓存

2018-07-08 15:57:06  [ main:0 ] - [ INFO ]  {dataSource-1} inited
2018-07-08 15:57:06  [ main:53 ] - [ DEBUG ]  Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
进行第一次查询
2018-07-08 15:57:06  [ main:79 ] - [ DEBUG ]  Opening JDBC Connection
2018-07-08 15:57:06  [ main:83 ] - [ DEBUG ]  Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@9a7504c]
2018-07-08 15:57:06  [ main:90 ] - [ DEBUG ]  ==>  Preparing: select * from book 
2018-07-08 15:57:06  [ main:137 ] - [ DEBUG ]  ==> Parameters: 
2018-07-08 15:57:06  [ main:163 ] - [ DEBUG ]  <==      Total: 7
2018-07-08 15:57:06  [ main:164 ] - [ DEBUG ]  ==>  Preparing: delete from book where id=? 
2018-07-08 15:57:06  [ main:165 ] - [ DEBUG ]  ==> Parameters: 7(Integer)
2018-07-08 15:57:06  [ main:168 ] - [ DEBUG ]  <==    Updates: 1
进行第二次查询
2018-07-08 15:57:06  [ main:168 ] - [ DEBUG ]  ==>  Preparing: select * from book 
2018-07-08 15:57:06  [ main:168 ] - [ DEBUG ]  ==> Parameters: 
2018-07-08 15:57:06  [ main:171 ] - [ DEBUG ]  <==      Total: 6

二级缓存

mybatis使用二级缓存的话只需要在mapper标签里面加一个<cache/>

测试二级缓存,二级缓存是跨session的,如果使用二级缓存,则必须要提交事务

package sdibt.lxj.test;

import org.apache.ibatis.session.SqlSession;
import sdibt.lxj.dao.IBookDao;
import sdibt.lxj.util.MybatisUtils;

public class TestMybatisCache {
	public static void main(String[] args) throws ClassNotFoundException {
		//创建两个session
		SqlSession session = MybatisUtils.getSession();				
		SqlSession session1 = MybatisUtils.getSession();						
		IBookDao dao = session.getMapper(IBookDao.class);
		IBookDao dao1 = session1.getMapper(IBookDao.class);
		
		dao.all();
		//提交事务
		session.commit();
		
		dao1.all();
		session1.commit();
	}
}
2018-07-08 17:31:21  [ main:0 ] - [ INFO ]  {dataSource-1} inited
2018-07-08 17:31:21  [ main:40 ] - [ DEBUG ]  Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
2018-07-08 17:31:21  [ main:101 ] - [ DEBUG ]  Cache Hit Ratio [sdibt.lxj.dao.IBookDao]: 0.0
2018-07-08 17:31:21  [ main:108 ] - [ DEBUG ]  Opening JDBC Connection
2018-07-08 17:31:21  [ main:111 ] - [ DEBUG ]  Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4923ab24]
2018-07-08 17:31:21  [ main:120 ] - [ DEBUG ]  ==>  Preparing: select * from book 
2018-07-08 17:31:21  [ main:166 ] - [ DEBUG ]  ==> Parameters: 
2018-07-08 17:31:21  [ main:197 ] - [ DEBUG ]  <==      Total: 7
2018-07-08 17:31:21  [ main:265 ] - [ DEBUG ]  Cache Hit Ratio [sdibt.lxj.dao.IBookDao]: 0.5

实验,当某一个session对数据库进行了修改,其他session共享的二级缓存是否失效

package sdibt.lxj.test;

import org.apache.ibatis.session.SqlSession;
import sdibt.lxj.dao.IBookDao;
import sdibt.lxj.util.MybatisUtils;

public class TestMybatisCache {
	public static void main(String[] args) throws ClassNotFoundException {
		//创建两个session
		SqlSession session = MybatisUtils.getSession();				
		SqlSession session1 = MybatisUtils.getSession();						
		SqlSession session2 = MybatisUtils.getSession();						
		IBookDao dao = session.getMapper(IBookDao.class);
		IBookDao dao1 = session1.getMapper(IBookDao.class);
		IBookDao dao2 = session2.getMapper(IBookDao.class);
		
		dao.all();
		//提交事务
		session.commit();
		
		dao2.delete1(1);
		session.commit();
		
		dao1.all();
		session1.commit();
	}
}

可以看到,在某一个 session执行了修改数据库的方法,仍然能命中缓存,说明二级缓存是不再session中的,所以如果要使用二级缓存,应该是一些不经常更新的数据

2018-07-08 17:35:17  [ main:0 ] - [ INFO ]  {dataSource-1} inited
2018-07-08 17:35:17  [ main:38 ] - [ DEBUG ]  Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
2018-07-08 17:35:18  [ main:100 ] - [ DEBUG ]  Cache Hit Ratio [sdibt.lxj.dao.IBookDao]: 0.0
2018-07-08 17:35:18  [ main:106 ] - [ DEBUG ]  Opening JDBC Connection
2018-07-08 17:35:18  [ main:110 ] - [ DEBUG ]  Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4923ab24]
2018-07-08 17:35:18  [ main:119 ] - [ DEBUG ]  ==>  Preparing: select * from book 
2018-07-08 17:35:18  [ main:163 ] - [ DEBUG ]  ==> Parameters: 
2018-07-08 17:35:18  [ main:194 ] - [ DEBUG ]  <==      Total: 7
2018-07-08 17:35:18  [ main:207 ] - [ DEBUG ]  Opening JDBC Connection
2018-07-08 17:35:18  [ main:207 ] - [ DEBUG ]  Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@710726a3]
2018-07-08 17:35:18  [ main:209 ] - [ DEBUG ]  ==>  Preparing: delete from book where id=? 
2018-07-08 17:35:18  [ main:209 ] - [ DEBUG ]  ==> Parameters: 1(Integer)
2018-07-08 17:35:18  [ main:210 ] - [ DEBUG ]  <==    Updates: 0
2018-07-08 17:35:18  [ main:213 ] - [ DEBUG ]  Cache Hit Ratio [sdibt.lxj.dao.IBookDao]: 0.5

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值