mybatis分为一级缓存和二级缓存。
mybatis默认开启一级缓存。
如何解析:
执行者:XmlConfiguraBuilder类
解析对象:mybatis所有的配置信息
目标:Configuration(包含数据源、事务、mapper等的配置的对象)
sqlSession是什么:
mybatis的关键对象,也是一级缓存的作用域,
相当于JDBC的Connection,底层封装了JDBC连接,通过它操作数据库。
线程不安全的,不能被共享。
一级缓存(sqlSession级别):
实现:
Executor 1.构造cacheKey去PerpectualCache中去查询对应的结果value
2.没有,就去数据库中去查,将查询结果保存到PerpectualCache中,然后再返回。
备注:
一级缓存实际上是使用PerpetualCache来维护的,内部使用一个HashMap,
key(cacheKey)为hashcode+statementId+sql语句。Value为查询出来的结果集映射成的java对象。
当ddl的时候会清空sqlSession的缓存。
看图理解:
二级缓存(Mapper级别):
实现:
Executor 1. 让Executor 的装饰者CachingExecutor去二级缓存查
2.没有,就让真正的Executor去一级缓存去查。
注:每个Mapper有一个Cache,多个Mapper可以通过cache-ref公用一个Cache
看图理解:
二级缓存实现方式:
1.Mybatis自身提供
2.自定义Cache接口
3.第三方中间件
开启二级缓存:
1.Mybatis的配置文件SqlMapConfig.xml 中设置cacheEnabled为true;
2.Mapper.xml中设置Cache
3.select中配置useCache为true(默认为true)
4.映射的实体类需要序列化:
理由:由于二级缓存的数据不一定都是存储到内存中,它的存储介质多种多样,所以需要给缓存的对象执行序列化。
二级缓存存在的问题:
A,B二表联合查询,
结果放到MapperA的cache中(其中有B表此时的数据哦),
然后有对B表的update操作,会清空MapperB的cache,
但此时无法将MapperA中cache实时更新。
最佳解决方案:
用Enhanced-Cache来管理缓存。