Mybatis之缓存

Mybatis作为典型的持久层框架,下面聊聊其缓存。
1、概念

  • SqlSession:代表和数据库的一次会话,向用户提供了操作数据库的方法;
  • MappedStatement:代表要发往数据库执行的指令,可以理解为是 SQL 的抽象表示;
  • Executor:代表用来和数据库交互的执行器,接受 MappedStatment 作为参数;
  • Namespace:每个 Mapper 文件只能配置一个 namespace,用来做 Mapper 文件级别的缓存共享;
  • 映射接口:每个 Mapper 文件只能配置一个 namespace,用来做 Mapper 文件级别的缓存共享;
  • 映射文件:MyBatis 编写的 XML 文件,里面有一个或多个 SQL 语句,不同的语句用来映射不同的接口方法。通常来说,每一张单表都对应着一个映射文件;

2、Mybatis一级缓存
在一次 SqlSession 中,程序执行多次查询,且查询条件完全相同,多次查询之间程序没有其他增删改操作,则第二次及后面的查询可以从缓存中获取数据,避免走数据库。
每个SqlSession中持有了Executor,每个Executor中有一个LocalCache。当用户发起查询时,MyBatis根据当前执行的语句生成MappedStatement,在Local Cache进行查询,如果缓存命中的话,直接返回结果给用户,如果缓存没有命中的话,查询数据库,结果写入Local Cache,最后返回结果给用户。其中Local Cache 其实是一个 hashmap。
使用一级缓存场景:打开一个sqlsession,对同一个sql先后执行了3次,第一次从数据库查询到数据,后两次从一级缓存查询到数据。

// 打开一个 SqlSession
SqlSession sqlSession = factory.openSession(true);
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class); 
// 根据 id=1 查询学生信息
System.out.println(studentMapper.getStudentById(1)); 
// 根据 id=1 查询学生信息
System.out.println(studentMapper.getStudentById(1)); 
// 根据 id=1 查询学生信息
System.out.println(studentMapper.getStudentById(1));

若是第一次查询之后,执行了更新操作 ,则该条查询的一级缓存就失效了。一级缓存的作用范围为SqlSession。

3、Mybatis二级缓存
MyBatis二级缓存相对于一级缓存来说,实现了SqlSession之间缓存数据的共享,同时粒度更加的细,能够到namespace级别,通过Cache接口实现类不同的组合,对Cache的可控性也更强。
在分布式环境下,由于默认的MyBatis Cache实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将 MyBatis的Cache 接口实现,有一定的开发成本,直接使用Redis、Memcached 等分布式缓存可能成本更低,安全性也更高。
一级缓存最大的共享范围就是一个 SqlSession 内部,如果多个 SqlSession 之间需要共享缓存,则需要使用到二级缓存。开启二级缓存后,会使用 CachingExecutor 装饰 Executor,进入一级缓存的查询流程前,先在CachingExecutor 进行二级缓存的查询。二级缓存开启后,同一个 namespace下的所有操作语句,都影响着同一个Cache。

在使用Mybatis时,还可以整合第三方缓存实现自定义缓存。在工程应用时还需深入理解Mybatis的底层原理。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值