MyBatis的Cache机制

正如大多数持久层框架一样, MyBatis 同样提供了一级缓存二级缓存的支持

1. 一级缓存: 基于PerpetualCache 的 HashMap本地缓存, 其存储作用域为 Session, 当 Session flush 或 close 之后, 该Session中的所有 Cache 就将清空;
2. 二级缓存与一级缓存其机制相同, 默认也是采用 PerpetualCache, HashMap存储, 不同在于其存储作用域为 Mapper(Namespace), 并且可自定义存储源, 如 Ehcache;
3. 对于缓存数据更新机制, 当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后, 默认该作用域下所有 select 中的缓存将被clear.

一级缓存:

@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的一级缓存是默认开启的.

二级缓存:

@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查询了两次数据库

手动开启二级缓存:

实体类要实现序列化

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

总结:

1. 一级缓存默认开启
2.必须使用的是两个不同的session,并且第一个session必须提交才能使用二级缓存
3.查询条件一致才可以
4.session如果关闭了则失效了
5.映射文件中所有R操作将被缓存, 所有C/U/D操作会刷新缓存
6.感觉MyBatis的缓存作用不大, 面对一定规模的数据量, 内置的缓存方式就派不上用场了, 对查询结果集做缓存并不是MyBatis框架擅长的, 它专心做的应该是sql mapper. 采用此框架的Application去构建缓存更合理

点赞

发表评论