正确配置缓存能够提升系统的查询性能,这篇笔记我们以SpringBoot工程为例介绍MyBatis框架中和缓存相关的配置。
MyBatis的一级缓存和Hibernate类似,是SqlSession级别的缓存,且是默认启用的。我们开发者一般也不需要更改它的设置也感受不到它的存在,只要注意避免因缓存造成的bug即可(注:可能发生的bug是指查询得到的结果因缓存未得到及时更新,这个情况很难碰到)。
如果有必要,我们也可以指定强制刷新一级缓存,例子配置如下。
<select id="selectByid" flushCache="true" resultMap="userMap" >
select * from sys user where id = #{id}
</select>
这样配置<select>
标签后,每次查询都会刷新缓存,当然,这样做也会对性能产生影响。
除了一级缓存,MyBatis还具有内置的二级缓存功能。二级缓存是和命名空间(Mapper)绑定的,一个Mapper对应一组缓存,二级缓存可以在不同的SqlSession之间共享。二级缓存刷新时机主要依据如下判断:
<cache>
中的设置刷新缓存MyBatis框架内有一个默认的基于哈希表的二级缓存实现,但我们一般还是习惯于用EhCache等成熟的缓存框架作为底层的缓存实现。具体到MyBatis框架中,二级缓存需要实现org.apache.ibatis.cache.Cache
接口的类,不过我们不必自己开发,MyBatis官方提供了和EhCache集成的库。下面例子中,我们引入了MyBatis集成EhCache的依赖。
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.1.0</version>
</dependency>
在SpringBoot工程中,我们可以配置mybatis.configuration.cache-enabled
为true
开启二级缓存功能。
mybatis.configuration.cache-enabled=true
此外,在Mapper的映射XML中,我们还需要配置<cache>
标签指定使用缓存。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gacfox.demomb.dao.RoleMapper">
<cache type="org.mybatis.caches.ehcache.EhcacheCache" eviction="LRU" size="1024" readOnly="false"/>
<select id="selectAllRoles" resultType="com.gacfox.demomb.model.Role">
select role_id as roleId, rolename
from t_role
</select>
</mapper>
<cache>
标签有入下几个可配置选项:
type
:缓存的提供类全名,比如使用EhCache这个值就是org.mybatis.caches.ehcache.EhcacheCache
eviction
:缓存策略,如LRU(默认)
,FIFO
等,都很好理解size
:缓存的引用数,默认1024个readOnly
:是否为只读缓存,默认为false
,只读缓存使用Map会给调用者返回相同的实例,因此这些对象不能修改否则就容易出bug,可读写缓存会通过序列化返回缓存对象的拷贝,但也因此性能不如只读缓存。flushInterval
:缓存刷新时间,默认不定时刷新,只在调用语句时刷新另外,我们的实体类还需要实现Serializable
接口,以便对象能够存储到缓存系统中。
如果想要基于Redis实现二级缓存,MyBatis并没有提供类似EhCache的mybatis-redis
库(早年存在这个库但官方弃坑了),但编写一个兼容MyBatis的二级缓存组件也并不困难。
此外我们还有另一种选择,我们可以使用SpringCache库。SpringCache是一个Spring提供的声明式缓存管理组件,它没有和MyBatis直接集成,但它的功能允许我们将其和MyBatis结合使用,这部分可以参考SpringCache相关章节。