正如大多数持久层框架一样, MyBatis 同样提供了一级缓存和二级缓存的支持
1. 一级缓存: 基于PerpetualCache 的 HashMap本地缓存, 其存储作用域为 Session, 当 Session flush 或 close 之后, 该Session中的所有 Cache 就将清空;
2. 二级缓存与一级缓存其机制相同, 默认也是采用 PerpetualCache, HashMap存储, 不同在于其存储作用域为 Mapper(Namespace), 并且可自定义存储源, 如 Ehcache;
3. 对于缓存数据更新机制, 当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后, 默认该作用域下所有 select 中的缓存将被clear.
[title]一级缓存:[/title]
@Test
public void testgetUserById() {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User u1=mapper.getUserById(1);
System.out.println(u1);
User u2=mapper.getUserById(1);
System.out.println(u2);
sqlSession.commit();
} finally {
sqlSession.close();
}
}
通过打印SQL日志可以看到只执行了一次查询, MyBatis的一级缓存是默认开启的.
[title]二级缓存:[/title]
@Test
public void testCache2() {
SqlSession sqlSession = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
try {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
User u1=mapper.getUserById(1);
System.out.println(u1);
sqlSession.commit();
User u2=mapper2.getUserById(1);
System.out.println(u2);
sqlSession2.commit();
} finally {
sqlSession.close();
}
}
没开启二级缓存的情况下: 通过查看SQL日志可以看到MyBatis查询了两次数据库
[title]手动开启二级缓存:[/title]
实体类要实现序列化
public class User implements Serializable
MyBatis配置文件开启二级缓存
<setting name="cacheEnabled" value="true" />
映射文件中加入配置
<?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.mcdao.dao.mapper.UserDao">
<cache />
</mapper>
测试查看日志, 只执行了一次SQL
[title]总结:[/title]
1. 一级缓存默认开启
2.必须使用的是两个不同的session,并且第一个session必须提交才能使用二级缓存
3.查询条件一致才可以
4.session如果关闭了则失效了
5.映射文件中所有R操作将被缓存, 所有C/U/D操作会刷新缓存
6.感觉MyBatis的缓存作用不大, 面对一定规模的数据量, 内置的缓存方式就派不上用场了, 对查询结果集做缓存并不是MyBatis框架擅长的, 它专心做的应该是sql mapper. 采用此框架的Application去构建缓存更合理
文章评论