目录
- mybatis作用域
- 一级缓存
- 二级缓存
1.mybatis作用域
作用域 | 作用 | 范围 |
---|---|---|
SqlSessionFactoryBuilder | 创建SqlSessionFactory对象,创建完成后自身销毁 | 方法作用域 |
SqlSessionFactory | 应用中一直存在,用于创建SqlSession | 应用作用域 |
SqlSession | 每个线程都有一个自身的SqlSession,执行完成后关闭 | 会话作用域 |
Mapper | 绑定映射的语句的接口 | 同上相当 |
2. 一级缓存
2.1 简单示意图
2.2 生命周期
- 开启会话时由SqlSessionFactory创建一个新的SqlSession对象,该对象中会有一个新的Executor对象,Executor对象中持有一个新的PerpetualCache对象;当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉。
- 如果SqlSession调用了close()方法,会释放掉一级缓存PerpetualCache对象,一级缓存将不可用;
- 如果SqlSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是该对象仍可使用;
- SqlSession中执行了任何一个update操作(update()、delete()、insert()) ,都会清空PerpetualCache对象的数据,但是该对象可以继续使用;
3. 二级缓存
3.1 简单示意图
3.2 生命周期
- 映射语句中的所有的select语句都将会被缓存
- 映射语句文件中的所欲insert、update和delete语句会刷新缓存
- 缓存会使用默认的Least Recently Used(LRU,最近最少使用的)算法来收回
4. mybatis和spring结合后一级缓存失效
mybatis的一级缓存主要由SqlSession来进行控制,而spring对mybatis的SqlSession由template控制,sqlsession又被spring当作resource放在当前线程的上下文里(threadlocal),spring通过mybatis调用数据库的过程如下:
- 我们需要访问数据
- spring检测到之后,spring去资源池申请一个mybatis的SqlSession,并将申请到的sqlsession与当前线程绑定,放入threadlocal里面
- template从threadlocal获取到sqlsession,去执行查询
- 查询结束,清空threadlocal中与当前线程绑定的sqlsession,释放资源
- 我们又需要访问数据
- 返回到步骤
通过以上步骤后发现,同一线程里面两次查询同一数据所使用的sqlsession是不相同的,所以,给人的印象就是结合spring后,mybatis的一级缓存失效了。
参考资料:
https://blog.csdn.net/chenyao1994/article/details/79233725
https://www.cnblogs.com/happyflyingpig/p/7739749.html