MyBatis缓存机制之一级缓存

11 篇文章 0 订阅
4 篇文章 0 订阅

MyBatis缓存机制之一级缓存

前言

        MyBatis内部封装了JDBC,简化了加载驱动、创建连接、创建statement等繁杂的过程,是我们常见的持久性框架。缓存是在计算机内存中保存的临时数据,读取时无需再从磁盘中读取,从而减少数据库的查询次数,提高执行效率。Mybatis提供了一级缓存和二级缓存的支持,默认情况下只开启一级缓存。本次将带着大家深入了解Mybatis的一级缓存机制。

介绍

        当我们访问数据库时,Mybatis会创建出一个SqlSession对象开启一次数据库会话。在这次会话中,我们可能会执行多次相同的查询语句,如果不采取措施,每一次查询都会访问数据库,造成资源的浪费。为了优化这部分场景,Mybatis提供了一级缓存的方案,如果是相同的SQL语句,会优先命中一级缓存,避免直接对数据库进行查询。具体执行过程如下图所示。

         每个SqlSession中都持有Executor执行器,每个Excutor中有一个LocalCache缓存。Mybatis根据当前执行的SQL生产MappedStatement,在缓存中进行查询,如果缓存命中的话,直接返回结果给用户,如果缓存没有命中,查询数据库,结果写入LocalCache,再返回结果给用户。具体实现类的类关系图如下所示:

 

源码分析

我们将对MyBatis的源码进行分析,深入理解底层原理。

        SqlSession: SqlSession是应用程序与持久层执行交互操作的单线程对象,代表着一个资源的启用,包含所有执行SQL操作的方法。默认实现类是DefaultSqlSession。

        主要作用:1、获取Mapper接口;2、发送SQL给数据库;3、控制数据库事务

         Executor执行器:Executor定义了查询、更新、事务、缓存操作相关的接口方法,由SqlSession依赖,并受其调度与管理。核心功能是调度执行SQL。在Executor内部完成对LocalCache的查询和写入。

 

 Cache:Mybatis中的Cache接口,提供了缓存的基本操作。

         PerpetualCache是对Cache接口最基本的实现,其原理非常简单,内部持有HashMap,对一级缓存的操作实则是对HashMap的操作。如下代码所示:

        客户端与数据库的交互,首先通过DefaultSqlSessionFactory开启SqlSession:

                 在初始化SqlSession时,会通过configuration类创建一个新的Executor:

         SqlSession创建完毕后,根据不同类型的Statement,SqlSession会执行对应的方法。比如Select语句,最终会执行到selectList方法

        SqlSession把具体的查询交给Executor去执行。如果只开启了一级缓存的话,首先会进入BaseExecutor的query方法。代码如下所示:

        会根据传入的参数生成CacheKey作为唯一标识,进入方法,查看具体的生成逻辑:

        在上述的代码中,将MappedStatement的Id、SQL的offset、SQL的limit、SQL本身以及SQL中的参数传入了CacheKey这个类,最终构成CacheKey。在CacheKey的update方法中,会进行一个hashcode和checksum的计算,同时把传入的参数添加进updatelist中。如下代码所示:

 只要两条SQL的下列五个值相同,即可以认为是相同的SQL。

Statement Id + Offset + Limmit + Sql + Params

如果在LocalCache查不到的话,就会查询数据库,并将结果写入至缓存。

         如果是insert/update/delete方法,统一都会走SqlSession的update流程,同样委托执行器执行SQL。

        执行方法如下,我们可以发现每次执行update前都会清空LocalCache。所以当发生修改操作时,一级缓存会失效,防止了数据脏读。

 总结

1、一级缓存LocalCache只是BaseExecutor的一个字段。所以,当SqlSession的生命周期结束时,一级缓存也会被回收。

2、一级缓存由PerpetualCache实现,其内部通过HashMap完成对缓存的读写操作,所以本质上讲,一级缓存其实是通过HashMap实现的,Map中的key是由MappedStatement生成CacheKey,来确保查询的唯一性。

3、MyBatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,数据库写操作会引起脏数据,建议设定缓存级别为Statement。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值