MyBatis 内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制。
一、一级缓存
默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。一级缓存也就是本地缓存:
- 与数据库同一次会话期间查询到的数据都放在本地缓存中。
- 如果同一次会话中的后面要查询相同的数据,直接从缓存中拿,不会再去数据库查询了。
编写例子测试一下:
mapper接口:
User selectUserById(@Param("id") int id);
xml实现:
<resultMap id="userMap" type="mybatis09.domain.User">
<result column="id" property="id" />
<result column="name" property="userName" />
<result column="password" property="password" />
</resultMap>
<select id="selectUserById" resultMap="userMap">
select * from public.user where id = #{id}
</select>
junit测试:
@Test
public void selectUserById() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user1 = userMapper.selectUserById(1);
System.out.println(user1);
User user2 = userMapper.selectUserById(1);
System.out.println(user2);
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
}
注意到,这里查询了两次id为1的用户。
查询结果:
这里在一个jdbc连接中就完成了查询,第二个User不再使用sql语句去查询,而是直接从缓存中查出来了。
如果我们查不同的id,查看结果如下:
一个会话就一次jdbc连接,但是这里查了两次sql。
如果中间有出现增删改 操作,mybatis就会去刷新缓存。
小结: 一级缓存是默认开启的,只在一次sqlSession中有效。
二、二级缓存
要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行:<cache/> ,但前提是开启了全局缓存配置(默认是开启的):
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
二级缓存是基于命名空间的,也即是说,一个mapper对应一个二级缓存。在一级缓存中,如会话关闭了,那一级缓存就丢失了。在使用了二级缓存后,会话关闭后会将一级缓存中的数据保存到二级缓存中。在新的会话查询数据时,就可以直接从二级缓存中获取数据。
xml实现:
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
<resultMap id="userMap" type="mybatis09.domain.User">
<result column="id" property="id"/>
<result column="name" property="userName"/>
<result column="password" property="password"/>
</resultMap>
<select id="selectUserById" resultMap="userMap" useCache="true">
select * from public.user where id = #{id}
</select>
在UserMapper.xml中使用了<cache /> 标签,并且在<select> 语句中显式添加了useCache="true" (默认开启的)。
查询结果:
在第一次sqlSession关闭之后,将数据保存到二级缓存中了。第二次sqlSession会话查询的时候,直接从缓存中获取到了数据。
Cache Hit Ratio [mybatis09.mapper.UserMapper]: 0.5
小结:
- 只要开启了二级缓存,在同一个Mapper下都有效。
- 所有的数据会先放在一级缓存中,等会话结束再保存到二级缓存中。
- 先查二级缓存,如果没有再找一级缓存,如果还没有才去找数据库。
|