mybatis——一级缓存、二级缓存
一、Mybatis缓存
● MyBatis包含一个非常强大的查询緩存特性,它可以非常方便地定制和配置缓存。绶存可以极大的提升查询效率。
● MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存
○ 默认情况下,只有一级缓存开启。( SqlSession级别的缓存,也称为本地缓存)
○ 二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
○ 为了提高扩展性, MyBatis定义了缓存接口 Cache。我们可以通过实现 Cache接口来自定义二级缓存
注:缓存的作用就是提升查询的效率。
二、一级缓存
● 一级缓存也叫本地缓存
○ 与数据库同一次会话期间查询到的数据会放在一级缓存中。
○ 以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库。
注:一级缓存默认是开启的,只在一次 Sqlsession中有效,也就是拿到连接到关闭连接这个区间段!
三、二级缓存
● 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存。
● 基于namespace级别的缓存,一个名称空间(namespace)对应一个二级级存
● 工作机制
○ 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
○ 如果当前会话关闭了,这个会 被保存到二级缓存中;
○ 新的会话查询信息,就可以从二级缓存中获取内容;
○ 不同的mappe查出的数据会放在自己对应的缓存(map)中;
开启二级缓存步骤:
1.在核心配置文件中添加一个settings标签,如下所示:
<settings> <setting name="cacheEnable" value="true"/> </settings>
2.在SQL 映射文件中添加一行:
<cache/>
也可以自定义参数
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。
可用的清除策略有:
- LRU – 最近最少使用:移除最长时间不被使用的对象。
- FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
- SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。
- WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。
默认的清除策略是 LRU。
flushInterval(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。如果设置了,就会在指定时间周期清空一次缓存。
size(引用数目)属性可以被设置为任意正整数,要注意缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。
readOnly(只读)属性可以被设置为 true 或 false。设置为true时mybatis会直接给调用者返回缓存对象的引用,因此不安全(因为拿到引用后就可以对缓存中的数据进行修改),但是提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全。默认值是 false。
注意:
开启二级缓存的话,且设置readOnly为false(默认值)时,我们的pojo类就必须实现序列化接口,因为mybatis会通过序列化与反序列化机制返回一个缓存中对象的拷贝。
所有的数据都会先放在一级缓存中,只有当会话提交,或者关闭的时候,才会提交到二级缓存中!
如果开启了二级缓存,mybatis会先从二级缓存中提取数据。若在二级缓存中没有找到数据,则再去一级缓存中查找。一级缓存中也找不到数据,就会去查询数据库并且把查询结果保存到一级缓存中。