这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战
Mybatis一级缓存
前提
Mybatis的一级缓存一般SqlSession级别的,是默认开启的
在将源码解析之前,需要带着以下几个疑问进行阅读
- 一级缓存到底是什么?
- 一级缓存什么时候被创建?
- 一级缓存的工作流程是什么?
一级缓存是什么?
打开SqlSession发现,目前跟只有clearCache()
方法跟缓存有关系
点开clearCache()
按照以下顺序依次点开
再深⼊分析,流程⾛到Perpetualcache
中的clear()
⽅法之后,会调⽤其cache.clear()
⽅法,那么这个cache是什么东⻄呢?点进去发现,cache其实就是private Map<Object, Object> cache = new HashMap<>();
HashMap();也就是⼀个Map,所以说cache.clear()其实就是map.clear(),也就是说,缓存其实就是本地存放的⼀个map对象,每⼀个SqISession都会存放⼀个map对象的引⽤。那么第一个疑问就已经能够解答,一级缓存本质上是一个HashMap对象。
一级缓存什么时候被创建的?
一般来讲,是在Executor中创建的,因为Executor是执行器,用来执行sql请求,⽽且清除缓存的⽅法也在Executor中执⾏,所以很可能缓存的创建也很有可能在Executor中。我们可以看看Executor方法:
Executor中有⼀个createCacheKey()
⽅法,这个⽅法是创建缓存的⽅法啊,跟进去看看,你发现createCacheKey()
⽅法是由BaseExecutor执⾏的,createCacgeKey()
代码如下:
1 | java复制代码CacheKey cacheKey = new CacheKey(); |
创建缓存key会经过⼀系列的update⽅法,udate⽅法由⼀个CacheKey这个对象来执⾏的,这个update⽅法最终由updateList的list来把五个值存进去,对照上⾯的代码和下⾯的图示,你应该能理解这五个值都是什么了
这⾥需要注意⼀下最后⼀个值,configuration.getEnvironment().getId()这是什么,这其实就是定义在mybatis-config.xml中的标签,⻅如下。
所以一级缓存是在执行器的子类BaseExecutor的createCacgeKey()方法中创建的。
一级缓存的工作流程?
一级缓存工作流程图
通过BaseExecutor的query()方法,代码如下
1 | java复制代码public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { |
1 | java复制代码@SuppressWarnings("unchecked") |
1 | java复制代码private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { |
通过上述代码,客户端调用query()
方法,query()
方法进过一系列的转换后拿到转换后的boundSql,并且创建Cache缓存,然后一起传入下一个query()
方法中,query()方法通过一个三元表示式表示如果查不到的话,就从数据库查,在queryFromDatabase()
方法中,会对localcache进⾏写⼊。localcache对象的put⽅法最终交给Map进⾏存放。这个就是基本一级缓存工作流程
1 | java复制代码private Map<Object, Object> cache = new HashMap<Object, Object>(); |
本文转载自: 掘金