mybatis 缓存总结

一级缓存

MyBatis 默认开启了一级缓存,一级缓存是在SqlSession 层面进行缓存的。即,同一个SqlSession ,多次调用同一个Mapper和同一个方法的同一个参数,只会进行一次数据库查询,然后把数据缓存到缓冲中,以后直接先从缓存中取出数据,不会直接去查数据库。

​ 但是不同的SqlSession对象,因为不同的SqlSession都是相互隔离的,所以相同的Mapper、参数和方法,他还是会再次发送到SQL到数据库去执行,返回结果。




二级缓存
      二级缓存是mapper级别的缓存,它的实现机制跟一级缓存差不多,也是基于PerpetualCache的HashMap本地存储。作用域为mapper的namespace,可以自定义存储,比如Ehcache。Mybatis的二级缓存是跨Session的,每个Mapper享有同一个二级缓存域. 

Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的Java对象。

二级缓存是需要配置来开启的:
[XML]  纯文本查看  复制代码
?
1
< setting name = "cacheEnabled" value = "true" />

非常简单,在Mybatis的核心配置文件中加上上面这行代码,然后在Mapper映射文件中添加一行:
[XML]  纯文本查看  复制代码
?
1
< cache eviction = "FIFO"  flushInterval = "60000"  size = "512"  readOnly = "true" />

表示开启二级缓存,flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。 size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。 readOnly(只读)属性可以被设置为true或false。 
只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。

如果已经开启二级缓存的mapper里面某个查询不需要缓存,可以使用useCache=”false”禁用二级缓存:
[XML]  纯文本查看  复制代码
?
1
< select id = "selectByPrimaryKey" resultMap = "BaseResultMap" parameterType = "java.lang.String" useCache = "false" >

刷新缓存: 

在mapper的同一个namespace中,如果有其他insert、update、delete操作后都需要执行刷新缓存操作,来避免脏读。 

这时我们只需要设置statement配置中的flushCache=“true“属性,就会默认刷新缓存,相反如果是false就不会了。 
当然,不管开不开缓存刷新功能,你要是手动更改数据库表,那都肯定不能避免脏读的发生,那就属于手贱了。
      无论是一级缓存还是二级缓存,C/U/D增删改操作commit提交后会清空缓存区域,使缓存失效。合理利用二级缓存可以提高系统性能,减少数据库压力。但是,如果使用不当可那个会出现缓存一致性问题,对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度。




mybatis在一个事物中获取oracle中的sequence,一开始没有问题,每次都返回不同的值,运行几天之后,批量处理三条数据,返回的是同一个sequence;

mybatis  xml文件中的sql如下:
 

以下四种解决方法,本人用的第二种:

1.拿出@Transactional,就不会出错。

2.加上useCache="false" flushCache="true",不保存在二级缓存中,并清空缓存

3.mybatis.configuration.localCacheScope=STATEMENT,修改一级缓存的作用域

4.mybatis.configuration.cacheEnabled = false,禁用一级和二级缓存
发布了604 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/xiaoyaGrace/article/details/104251402
今日推荐