MyBatis原理--缓存机制

原文网址:MyBatis原理--缓存机制_IT利刃出鞘的博客-CSDN博客_mybatis原理

简介

说明

Mybatis的缓存,包括一级缓存和二级缓存。

一级缓存的作用域是一个sqlsession内;二级缓存作用域是针对mapper进行缓存。

实际上,在开发过程中根本不会用到Mybatis的这两个缓存。因为这两个都不支持分布式,如果想用缓存,那么直接用Redis的功能就好了呀。虽然二级缓存可以使用MemCache、Ehcache、Redis等可以做到支持分布式,但不如直接使用Redis方便。

一级缓存

概述

简介

开启一级缓存后:在参数和SQL完全一样的情况下,同一个SqlSession对象调用一个Mapper方法,只执行一次SQL。因为使用SelSession第一次查询后,MyBatis会将其放在缓存中,以后再查询的时候,如果没有声明需要刷新,并且缓存没有超时的情况下,SqlSession都会取出当前缓存的数据,而不会再次发送SQL到数据库。

一级缓存的缺点

  1. 多个 SqlSession 或者分布式的环境下,数据库写操作会引起脏数据。
  2. MyBatis 一级缓存内部设计简单,只是一个没有容量限定的 HashMap,在缓存的功能性上有所欠缺

一级缓存命中条件

  1. 相同的 sql 和参数
  2. 会话(Session)级别缓存,必须是相同的会话
  3. 相同的方法
  4. 相同的 namespce (mapper)

一级缓存清除场景

  1. 增删改操作后,执行了commit
  2. 关闭了sqlSession
  3. 调用了clearCache(),或者查询语句中包含了flush

启用与关闭

MyBatis中一级缓存默认是开启的。

关闭单个SQL的一级缓存的方法:将flushCache属性设置为true。示例如下

<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap" flushCache="true">
  select 
  <include refid="Base_Column_List" />
  from cbondissuer
  where OBJECT_ID = #{objectId,jdbcType=VARCHAR}
</select>

关闭所有SQL的一级缓存的方法:在MyBatis的主配置文件中,关闭所有的一级缓存:设置localCacheScope。示例如下:

<setting name="localCacheScope" value="SESSION"/>
  1. value的值
    1. SESSION:在一个 MyBatis 会话中执行的所有语句,都共享这一个缓存
    2. STATEMENT:缓存只对当前执行的这一个 Statement 有效

详述

每个SqlSession 中持有 Executor,每个 Executor 中有一个 LocalCache。当用户发起查询时,MyBatis 根据当前执行的语句生成 MappedStatement,在 LocalCache 进行查询,如果缓存命中,就直接返回给用户,如果缓存没有命中的话,就另外查询数据库,将结果写入 LocalCahe,最后将结果返回给用户。

一级缓存的获取流程

  1. 对于某个查询,根据statementId,params,rowBounds来构建一个key值,根据这个key值去缓存Cache中取出对应的key值存储的缓存结果;
  2. 判断从Cache中根据特定的key值取的数据数据是否为空,即是否命中;
    1. 如果命中,则直接将缓存结果返回;
    2. 如果没命中:
      1. 去数据库中查询数据,得到查询结果;
      2. 将key和查询到的结果分别作为key,value对存储到Cache中;
  3. 将查询结果返回;
  4. 结束。

缓存的key的确定

Cache最核心的实现其实就是一个Map,将本次查询使用的特征值作为key,将查询结果作为value存储到Map中。

现在最核心的问题出现了:怎样来确定一次查询的特征值?
换句话说就是:怎样判断某两次查询是完全相同的查询?
也可以这样说:如何确定Cache中的key值?

MyBatis认为,对于两次查询,如果以下条件都完全一样,那么就认为它们是完全相同的两次查询:

  1. 传入的 statementId
  2. 查询时要求的结果集中的结果范围 (结果的范围通过rowBounds.offset和rowBounds.limit表示);
  3. 这次查询所产生的最终要传递给JDBC java.sql.Preparedstatement的Sql语句字符串(boundSql.getSql() )
  4. 传递给java.sql.Statement要设置的参数值

上边只是部分内容,为便于维护,本文已迁移到此地址:MyBatis原理-缓存机制 - 自学精灵

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT利刃出鞘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值