mybatis-缓存
- 1为什么用缓存
- 2mybatis缓存
- 2.1 一级缓存
- 2.2 二级缓存
- 2.3 Cache
- 3 一级缓存
- 一级缓存失效的四种情况
- 不同的SqlSession对应不同的一级缓存
- 同一个SqlSession但是查询条件不同
- 同一个SqlSession两次查询期间执行了增删改操作
- 同一个SqlSession两次查询期间手动清空了缓存
- 一级缓存失效的四种情况
- 4 二级缓存
- 缓存相关属性
- 缓存有关设置
1为什么用缓存
缓存机制减轻数据库压力,提高数据库性能,高性能、高并发。
2mybatis缓存
MyBatis系统中默认定义了两级缓存,一级缓存和二级缓存。
2.1 一级缓存
默认情况下,只有一级缓存(SqlSession级别的缓存,也称为本地缓存)开启,它仅仅对一个会话中的数据进行缓存,Mybatis一级缓存的执行过程:首次执行sql语句会从数据库获取数据,这些数据被存储在一段高速缓存中,再次执行这条语句时在没有进行增删改操作的前提下就会从高速缓存中获取数据而不是查询数据库。
2.2 二级缓存
二级缓存是基于namespace级别的缓存,需要手动开启,当一个SqlSession关闭后,它所存储的数据会放到mapper namespace的二级缓存区。
2.3 Cache
为了提高扩展性。MyBatis定义了缓存接口Cache。可以通过实现Cache接口来自定义二级缓存。
3 一级缓存
@Test
public void test2() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
TeacherMapper mapper1 = sqlSession.getMapper(TeacherMapper.class);
Teacher teacher1 = mapper1.getTeacherById(1);
System.out.println("==============");
Teacher teacher2 = mapper1.getTeacherById(1);
System.out.println(teacher1 == teacher2);
}
}
可以看到MyBatis进行了一次数据库查询
一级缓存失效的四种情况
不同的SqlSession对应不同的一级缓存
@Test
public void test2() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
TeacherMapper mapper1 = sqlSession.getMapper(TeacherMapper.class);
Teacher teacher1 = mapper1.getTeacherById(1);
System.out.println("==============");
SqlSession sqlSession1 = sqlSessionFactory.openSession();
TeacherMapper mapper2 = sqlSession1.getMapper(TeacherMapper.class);
Teacher teacher2 = mapper2.getTeacherById(1);
System.out.println(teacher1 == teacher2);
}
}
可以看到MyBatis进行了两次数据库查询
同一个SqlSession但是查询条件不同
@Test
public void test2() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
TeacherMapper mapper1 = sqlSession.getMapper(TeacherMapper.class);
Teacher teacher1 = mapper1.getTeacherById(1);
System.out.println("==============");
Teacher teacher2 = mapper1.getTeacherById(2);
System.out.println(teacher1 == teacher2);
}
}
可以看到MyBatis进行了两次数据库查询
同一个SqlSession两次查询期间执行了增删改操作
@Test
public void test2() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
TeacherMapper mapper1 = sqlSession.getMapper(TeacherMapper.class);
Teacher teacher1 = mapper1.getTeacherById(1);
System.out.println("==============");
Teacher teacher = new Teacher();
teacher.setId(1);
teacher.setTeaName("hhh");
mapper1.updateTeaSet(teacher);
Teacher teacher2 = mapper1.getTeacherById(1);
System.out.println(teacher1 == teacher2);
}
}
可以看到更新数据后缓存被清楚了。
同一个SqlSession两次查询期间手动清空了缓存
@Test
public void test2() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
TeacherMapper mapper1 = sqlSession.getMapper(TeacherMapper.class);
Teacher teacher1 = mapper1.getTeacherById(1);
System.out.println("==============");
sqlSession.clearCache();
Teacher teacher2 = mapper1.getTeacherById(1);
System.out.println(teacher1 == teacher2);
}
}
可以看到MyBatis进行了两次数据库查询
4 二级缓存
1)在MyBatis核心配置文件中开启二级缓存
2)在映射文件上添加标签:
@Test
public void test2() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
SqlSession sqlSession1 = sqlSessionFactory.openSession();
TeacherMapper mapper1 = sqlSession.getMapper(TeacherMapper.class);
Teacher teacher1 = mapper1.getTeacherById(1);
System.out.println("teacher1 = " + teacher1);
System.out.println("==============");
sqlSession.close();
TeacherMapper mapper2 = sqlSession1.getMapper(TeacherMapper.class);
Teacher teacher2 = mapper2.getTeacherById(1);
System.out.println("teacher2 = " + teacher2);
}
}
缓存相关属性
1)缓存相关属性:缓存相关属性:
? LRU – 最近最少使用的:移除最长时间不被使用的对象。
? FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
? SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
? WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
? 默认的是 LRU。
2)flushInterval:刷新间隔,单位毫秒
? 默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
3)size:引用数目,正整数
? 代表缓存最多可以存储多少个对象,太大容易导致内存溢出
4)readOnly:只读,true/false
? true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。
? false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是 false。
缓存有关设置
1)全局setting的cacheEnable:
配置二级缓存的开关。一级缓存一直是打开的。
2)select标签的useCache属性:
配置这个select是否使用二级缓存。一级缓存一直是使用的
3)sql标签的flushCache属性:
增删改默认flushCache=true。sql执行以后,会同时清空一级和二级缓存。查询默认flushCache=false。
4)sqlSession.clearCache():
只是用来清除一级缓存。
5)当在某一个作用域 (一级缓存Session/二级缓存Namespaces) 进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。