一级缓存
Mybatis每开启一次和数据库的会话,都会由SqlSessionFactory创建一个sqlSession 对象。并由这个sqlSession对象与数据库会话,实现数据的增删改查。
String resource = "mapper/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
try{
BlogMapper mapper = sqlSession.getMapper(XXXX.class)
mapper.....
}finally{
sqlSession.close();
}
在同一次sqlSession会话,我们有可能会反复执行相同的查询语句,如果每次查询都连接一次数据库并执行sql,这样做得到的结果极有可能是相同的,会造成很多的资源浪费。
Mybatis在表示会话的sqlSession对象中建立了一个相对简单的缓存。它将每次查询到的结果缓存起来。当前会话下次有一样的查询的时候,会直接从缓存中获取结果,而不需要再对数据库进行一次查询。
实际上,SqlSession把具体的实施过程交给一个叫Executor的执行器,这个执行器通过控制实现了Cache接口的PerpetualCache的对象进行一种比较简单的缓存管理。因此以及缓存的生命周期建立在一个SqlSession的基础上,如果这个SqlSession关闭了,当前的一级缓存就自动清空了。(如果使用clearCache()方法主动去清理缓存,也会使当前的一级缓存清空)
而在PerpetualCache内部,它实现了Cache接口,具体内容就是维护了一个HashMap<K,V>的对象,利用Map集合来管理一级缓存。这个key值是作为mybatis判断是否重复查询的条件,它根据传入的statementId、rowBounds(结果及的范围limit和offset)、param(参数)和Sql语句字符串一起来确定的。
因此可以整理一级缓存失效的几种情况:
- 不在同一个SqlSession内;
- 在同一个SqlSession内,但是查询的条件不同;
- 在同一个SqlSession内,但是两次相同查询中间有增删改的操作;
- 在同一个SqlSession内,但是利用clearCache()方法主动去清理了一级缓存;
二级缓存
说明
在Mybatis的默认设置中,二级缓存是不开启的,我们要开启二级缓存需要自己配置一些信息。前面说一级缓存的完整生命周期是在一次与数据库连接的SqlSession开启到关闭的这段时间内,且不同的SqlSession的一级缓存是不共享的。
二级缓存的生命周期是开启了二级缓存之后,在一次SqlSession关闭之后,将这次SqlSession中的一级缓存取出并存在在二级缓存中,并且是一直存在的,除非因为代码或者配置的条件让二级缓存被自动或手动清除了。
二级缓存也是基于nameSpace名称空间的缓存,一个nameSpace可以对应一个二级缓存(说白了就是我们要在对应的xml文件中通过配置开启当前名称空间的二级缓存)。
全局配置
在mybatis-config.xml文件中的settings设置中显式配置开启二级缓存,避免使用默认值因版本问题导致二级缓存未开启。
开启二级缓存
开启namespace二级缓存
开启当前namespace的二级缓存namespace可以理解为最上面Mapper标签中的type全类名。
参数说明:
- eviction:备选LRU 最近最少使用,移除时间最长的对象,FIFO先进先出,SOFT软引用(移除基于垃圾回收器状态和软引用规则的对象),WEAK弱引用
- flushInterval:填毫秒数,缓存多长时间清空一次。
- readOnly:填true或者false。为true的时候代表mybatis觉得操作是只读的不会进行数据修改,因此直接将数据索引交给用户,不安全但是速度快。为false的时候代表mybatis不相信数据,可能会被修改,因此克隆一份给用户,安全但是速度慢。这种克隆是基于序列化和反序列化实现的。因此要求javaBean对象是一定要实现了Seriealize序列化接口的。
- size:表示缓存对象的数量上限,超过了就要清除一些
- type:限定缓存对象的类型,可以不填直接使用默认的就行了
其他配置和配置说明
1、cacheEnabled这个配置配置为false时,只能关闭二级缓存,对一级缓存的使用是没有影响的。
2、每个select标签中都可以添加一个名为useCache的属性,这个属性为false时同样只能关闭二级缓存
3、flushCache:每个增删改的标签中都会有一个默认属性flushCache="true",它表示每次执行增删改会清空所有一级缓存和当前的名称空间的二级缓存。在查询标签Select中也可以配置这个参数,一般为false,表示查询不会清空当前会话的一级缓存和当前名称空间的二级缓存。
4、之前提过的sqlSession.clearCache()方法,此操作仅能清理当前会话的一级缓存。
5、全局配置localCacheScope 本地缓存作用域,它有两个备选值,一个是SESSION,一个是STATEMENT。SESSION表示本地缓存作用是在SqlSession环境下存储,是默认配置。配置STATEMENT则会关闭一级缓存。
网友评论