Mybatis一级缓存和二级缓存

目录


前言

        缓存可以将数据保存在内存中,是互联网系统常常用到的。目前流行的缓存服务器有 MongoDB、Redis、Ehcache 等。缓存是在计算机内存上保存的数据,读取时无需再从磁盘读入,因此具备快速读取和使用的特点。和大多数持久化框架一样,MyBatis 提供了一级缓存和二级缓存的支持。默认情况下,MyBatis 只开启一级缓存。

一、一级缓存

        一级缓存是基于 PerpetualCache(MyBatis自带)的 HashMap 本地缓存,作用范围为 session 域内。当 session flush(刷新)或者 close(关闭)之后,该 session 中所有的 cache(缓存)就会被清空。

在参数和 SQL 完全一样的情况下,我们使用同一个 SqlSession 对象调用同一个 mapper 的方法,往往只执行一次 SQL。因为使用 SqlSession 第一次查询后,MyBatis 会将其放在缓存中,再次查询时,如果没有刷新,并且缓存没有超时的情况下,SqlSession 会取出当前缓存的数据,而不会再次发送 SQL 到数据库。

由于 SqlSession 是相互隔离的,所以如果你使用不同的 SqlSession 对象,即使调用相同的 Mapper、参数和方法,MyBatis 还是会再次发送 SQL 到数据库执行,返回结果。 

       用一张图来表示一下一级缓存,其中每一个 SqlSession 的内部都会有一个一级缓存对象

1.工作流程: 

        常见术语:

                命中:需要的数据在缓存中找到结果

                未命中:需要的数据在缓存中没有找到结果

        流程:

  1. 对于某个 Select Statement,根据该 Statement 生成 key; 
  2. 判断在Local Cache中,该key是否用对应的数据存在;
  3. 如果命中,则跳过查询数据库,继续往下走;
  4. 如果没命中,去数据库中查询数据,得到查询结果;
  5. 将key和查询到的结果作为 key 和value,放入Local Cache 中;
  6. 将查询结果返回
  7. 判断缓存级别是否为 STATEMENT级别,如果是的话,清空本地缓存;

 2.实现效果:

Test.java

		SqlSession sqlSession = DaoUtil.getSqlSession();
		StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

		Student s1 = mapper.FindStudentBySid(4);
		System.out.println(s1);
		StudentMapper mapper1 = sqlSession.getMapper(StudentMapper.class);
		Student s2 = mapper.FindStudentBySid(4);
		System.out.println(s2);
		

 运行结果: 

可以看出我们创建两个mapper对象,分别调用了根据学号查找学生的方法,但是结果显示只查询了一次,第一查询之后将结果放在了缓存中,所以第二次再次调用同样的方法,就会直接去内存中找,如果有,就直接输出结果。

 3.缓存失效

  1. 同一个session单查询条件不同
        SqlSession sqlSession = DaoUtil.getSqlSession();
		StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

		Student s1 = mapper.FindStudentBySid(4);
		System.out.println(s1);

		Student s2 = mapper.FindStudentBySid(3);
		System.out.println(s2);

结果:

 

         2.同一个session两次查询期间执行了任何一次增删改操作

		SqlSession sqlSession = DaoUtil.getSqlSession();
		StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

		Student s1 = mapper.FindStudentBySid(4);
		
		int ret = mapper.deleteStudent(32);
		System.out.println(s1);
		if(ret>0) {
			sqlSession.commit();
			System.out.println("成功");
		}else {
			sqlSession.rollback();
			System.out.println("失败");
		}
		
		Student s2 = mapper.FindStudentBySid(4);
		System.out.println(s2);

结果:

         3.同一个session两次查询期间手动情况了缓存

		SqlSession sqlSession = DaoUtil.getSqlSession();
		StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

		Student s1 = mapper.FindStudentBySid(4);
		System.out.println(s1);
        //手动清除缓存
		sqlSession.clearCache();
		Student s2 = mapper.FindStudentBySid(4);
		System.out.println(s2);

 结果:

        4. 不同session对应不同的一级缓存 

二、二级缓存

1.配置

        第一种:在xml 文件中 

        第二种:注解的方式

        

 

2.工作原理

        底层是 HashMap 架构,二级缓存的作用域只在mapper级别的,也就是说无论你有多少个sqlSession去访问这个mapper,都会从缓存中获取到已有的数据mapper 对应的也就是 namespace,所以二级缓存是按照 namespace 进行区分的,如果两个 mapper 文件的 namespace 相同,那么这两个 mapper 中查出来的数据都会存在在这个 namespace 中。

 

3.二级缓存和一级缓存的区别

  •  一级是session级别的,二级是sessionFactory级别的
  • 工作原理不同,二级缓存是直接将数据反序列化到磁盘上,而一级缓存,访问同一个对象时,不用再去访问数据库
  • 二级缓存实现了缓存数据的共享,可控性更强,但容易出现错误数据,不推荐使用。

 

总结

        mybatis的的一级缓存是SqlSession级别的缓存,一级缓存缓存的是对象,当SqlSession提交、关闭以及其他的更新数据库的操作发生后,一级缓存就会清空。二级缓存SqlSessionFactory级别的缓存,同一个SqlSessionFactory产生的SqlSession都共享一个二级缓存,二级缓存中存储的是数据,当命中二级缓存时,通过存储的数据构造对象返回。查询数据的时候,查询的流程是二级缓存>一级缓存>数据库。

  • 19
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值