您的位置:首页 > 其它

Mybatis缓存机制

2017-12-07 15:26 232 查看
许多应用程序,为了提高性能而增加缓存, 特别是从数据库中获取的数据.如果缓存中没有,就到数据库中查询,查询到的数据添加到缓存,下次查询时就从缓存中取。MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。缓存可以极大的提升查询效率。

一、 mybatis 的一级缓存

在默认情况下,mybatis 的一级缓存是默认开启的。类似于hibernate, 所谓一级缓存,也就是基于同一个sqlsession 的查询语句,即 session 级别的缓存,非全局缓存,或者非二级缓存。

一级缓存(local cache), 即本地缓存, 作用域默认为sqlSession。当Session close 后, 该 Session 中的所有 Cache 将被清空。本地缓存不能被关闭, 但可以调用 clearCache()来清空本地缓存。

一级缓存失效的四种情况:

1、不同的SqlSession对应不同的一级缓存

2、同一个SqlSession但是查询条件不同

3、同一个SqlSession两次查询期间执行了任何一次增删改操作

4、同一个SqlSession两次查询期间手动清空了缓存

二 、mybatis 的二级缓存

如果要实现 mybatis 的二级缓存,二级缓存需要手动开启和配置,它是基于namespace级别的缓存,全局作用域缓存,一般来说有如下两种方式:

1. 采用 mybatis 内置的 cache 机制。

2. 为了提高扩展性,MyBatis定义了缓存接口Cache,我们可以通过实现Cache接口来自定义二级缓存,可以采用第三方cache 框架,比如ehcache, oscache,redis, memcached等等。

2.1 采用 mybatis 内置的 cache 机制。

在 sql 语句映射文件中加入 语句 , 并且相应的 model 类要实现 java Serializable 接口,因为二级缓存说白了就是序列化与反序列化的过程,所以需要实现这个接口. 单纯的 表示如下意思:

a.所有在映射文件里的 select 语句都将被缓存。

b.所有在映射文件里 insert,update 和 delete 语句会清空缓存。

c.缓存使用“最近很少使用”算法来回收

d.缓存不会被设定的时间所清空。

e.每个缓存可以存储 1024 个列表或对象的引用(不管查询出来的结果是什么) 。

f.缓存将作为“读/写”缓存,意味着获取的对象不是共享的且对调用者是安全的。不会有其它的调用者或线程潜在修改。

使用步骤:

1)全局配置文件中开启二级缓存,默认是开启的

<setting name="cacheEnabled" value="true"/>


2)需要使用二级缓存的映射文件处使用cache配置缓存

3)注意:POJO需要实现Serializable接口

4)如果会话关闭;一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,就可以参照二级缓存中的内容。二级缓存在 SqlSession 关闭或提交之后才会生效。

缓存元素的所有特性都可以通过属性来修改。

<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true" />


eviction:缓存的回收策略:

LRU – 最近最少使用的:移除最长时间不被使用的对象。

FIFO – 先进先出:按对象进入缓存的顺序来移除它们。

SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。

WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

默认的是 LRU。

flushInterval:缓存刷新间隔,缓存多长时间清空一次,默认不清空,设置一个毫秒值。

readOnly:是否只读:

true:只读;mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据,mybatis为了加快获取速度,直接就会将数据在缓存中的引用交给用户。不安全,速度快

false:非只读:mybatis觉得获取的数据可能会被修改,mybatis会利用序列化&反序列的技术克隆一份新的数据给你。安全,速度慢。

size:缓存存放多少元素。

type=”“:指定自定义缓存的全类名;实现Cache接口即可。

2.2采用 ehcache 来实现 mybatis的二级缓存

EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。MyBatis定义了Cache接口方便我们进行自定义扩展。

https://github.com/mybatis

步骤:

1)、导入ehcache包,以及整合包,日志包:

ehcache-core-2.6.8.jar、

mybatis-ehcache-1.0.3.jar,

slf4j-api-1.6.1.jar、

slf4j-log4j12-1.6.2.jar

2)编写ehcache.xml配置文件

3)配置cache标签

<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>


4)参照缓存:若想在命名空间中共享相同的缓存配置和实例。 可以使用 cache-ref 元素来引用另外一个缓存。

ehcache.xml配置文件属性说明:

diskStore:指定数据在磁盘中的存储位置。

defaultCache:当借助CacheManager.add(“demoCache”)创建Cache时,EhCache便会采用指定的的管理策略

以下属性是必须的:

maxElementsInMemory - 在内存中缓存的element的最大数目

maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大

eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断

overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上

以下属性是可选的:

timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大

timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大

diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.

diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。

diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作

memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)

缓存的执行流程:

当执行一条查询SQL时,流程为

1).从二级缓存中进行查询

2).进入一级缓存中查询

3).执行 JDBC 查询。

三、 和缓存有关的设置/属性

1、cacheEnabled=true:false:关闭缓存(二级缓存关闭)(一级缓存一直可用的)

2、每个select标签都有useCache=”true”:false:不使用缓存(一级缓存依然使用,二级缓存不使用)

3、每个增删改标签的:flushCache=”true”:(一级二级都会清除)增删改执行完成后就会清楚缓存;测试:flushCache=”true”:一级缓存就清空了;二级也会被清除;查询标签:flushCache=”false”:如果flushCache=true;每次查询之后都会清空缓存;缓存是没有被使用的;

4、sqlSession.clearCache();只是清楚当前session的一级缓存;

5、localCacheScope:本地缓存作用域:(一级缓存SESSION);当前会话的所有数据保存在会话缓存中;STATEMENT:可以禁用一级缓存;

a、全局setting的cacheEnable:配置二级缓存的开关。一级缓存一直是打开的。

b、select标签的useCache属性:配置这个select是否使用二级缓存。一级缓存一直是使用的

c、sql标签的flushCache属性:增删改默认flushCache=true。sql执行以后,会同时清空一级和二级缓存。查询默认flushCache=false。

d、sqlSession.clearCache():只是用来清除一级缓存。

e、当在某一个作用域 (一级缓存Session/二级缓存 Namespaces) 进行了 C/U/D 操作后,默认该作用域下所 有 select 中的缓存将被clear。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mybatis 缓存机制