MyBatis 包含一个强大的、可配置、可定制的查询缓存机制。MyBatis3 的缓存实现有了许多改进,使它更强大更容易配置。默认的情况,缓存是没有开启的,除了会话缓存以外,会话缓存可以提高性能,且能解决循环依赖。开启二级缓存,您只需要在 SQL 映射文件中加入简单的一行:
这句简单的语句作用如下:
• 所有映射文件里的 select 语句的结果都会被缓存。
• 所有映射文件里的 insert、update 和 delete 语句执行都会清空缓存。
• 缓存使用最近最少使用算法(LRU)来回收。
• 缓存不会被设定的时间所清空。
• 每个缓存可以存储 1024 个列表或对象的引用(不管查询方法返回的是什么)。
• 缓存将作为“读/写”缓存,意味着检索的对象不是共享的且可以被调用者安全地修改,而不会被其它调用者或者线程干扰。
所有这些特性都可以通过 cache 元素进行修改。例如:
这种高级的配置创建一个每 60 秒刷新一次的 FIFO 缓存,存储 512 个结果对象或列表的引用,并且返回的对象是只读的。因此在不用的线程里的调用者修改它们可能会引用冲突。
可用的回收算法如下:
• LRU:最近最少使用:移出最近最长时间内都没有被使用的对象。
• FIFO:先进先出:移除最先进入缓存的对象。
• SOFT:软引用:基于垃圾回收机制和软引用规则来移除对象(空间内存不足时才进行回收)。
• WEAK:弱引用:基于垃圾回收机制和弱引用规则(垃圾回收器扫描到时即进行回收)。
默认使用LRU
flushInterval:设置任何正整数,代表一个以毫秒为单位的合理时间。默认是没有设置,因此没有刷新间隔时间被使用,在语句每次调用时才进行刷新。
Size:属性可以设置为一个正整数,您需要留意您要缓存对象的大小和环境中可用的内存空间。默认是1024。
readOnly:属性可以被设置为 true 或 false。只读缓存将对所有调用者返回同一个实例。因此这些对象都不能被修改,这可以极大的提高性能。可写的缓存将通过序列化来返回一个缓存对象的拷贝。这会比较慢,但是比较安全。所以默认值是 false。
使用自定义缓存
除了上面已经定义好的缓存方式,您能够通过您自己的缓存实现来完全重写缓存行为,或者通过创建第三方缓存解决方案的适配器。
这个例子演示了如果自定义缓存实现。由 type 指定的类必须实现 org.mybatis.cache.Cache 接口。这个接口是 MyBatis 框架比较复杂的接口之一,先给个示例:
public interface Cache{ String getId(); int getSize(); void putObject(Object key,Object value); ObjectgetObject(Object key); boolean hasKey(Object key); Object removeObject(Object key); void clear(); ReadWriteLock getReadWriteLock();}
要配置您的缓存,简单地添加一个公共的 JavaBeans 属性到您的缓存实现中,然后通过 cache 元素设置属性进行传递,下面示例,将在您的缓存实现上调用一个 setCacheFile(String file) 方法。
您可以使用所有简单的 JavaBeans 属性,MyBatis 会自动进行转换。
需要牢记的是一个缓存配置和缓存实例都绑定到一个 SQL Map 文件命名空间。因此,所有的这个相同命名空间的语句也都和这个缓存绑定。语句可以修改如何与这个缓存相匹配,或者使用两个简单的属性来完全排除它们自己。默认情况下,语句像下面这样来配置:
因为有默认值,所以您不需要使用这种方式明确地配置这些语句。如果您想改变默认的动作,只需要设置 flushCache 和 useCache 属性即可。举个例子来说,在许多的场合下您可能排除缓存中某些特定的 select 语句。或者您想用 select 语句清空缓存。同样的,您也可能有一些 update 语句在执行的时候不需要清空缓存。
cache-ref元素回想上一节,我们仅仅只是讨论在某一个命名空间里使用或者刷新缓存。但有可能您想要在不同的命名空间里共享同一个缓存配置或者实例。在这种情况下,您就可以使用 cache-ref 元素来引用另外一个缓存。