介绍
MyBatis 中的缓存,主要分为一级缓存和二级缓存。
一级缓存是 SqlSession 级别的缓存,也叫本地缓存。当执行一个 SqlSession 的查询时,查询到的结果会被保存在 SqlSession 的缓存中。同一个 SqlSession 内执行相同的 SQL 语句,则会从缓存中获取数据,而不会再向数据库发出请求。一级缓存默认开启,不需要手动配置。
二级缓存是 Mapper 级别的缓存,也叫全局缓存。多个 SqlSession 共享一块缓存区域,从而减少了对数据库的访问次数。需要手动配置开启,在 Mapper.xml 文件中添加 <cache> 标签即可。
一般情况下,我们优先考虑使用一级缓存,因为它是自动开启的,可以避免一些可能的问题。如果在具体的场景中需要使用到二级缓存,可以单独配置。
需要注意的是,二级缓存虽然可以提升性能,但也带来了一些问题。如缓存的数据和数据库中的数据不一致等问题,因此在使用二级缓存时,需要谨慎处理缓存与数据库之间的数据同步问题。
如何关闭一次缓存,并开启二级缓存
Mybatis是Java语言中一种流行的持久化框架,主要用于关系型数据库操作。该框架通过映射配置文件将Java类映射到相应的数据库表中,并提供了一系列SQL执行的方法和优化机制。其中,flushCache和useCache是两个常见的缓存控制选项。
flushCache
flushCache是Mybatis提供的一个属性,当为true时,它会把该条SQL语句所在的缓存清除,这样可以在下次查询时不从缓存中读取,直接重新执行SQL语句查询数据库。
例如:
<select id="getUserById" parameterType="int" resultType="com.example.User" flushCache="true">
select * from user where id = #{id}
</select>
上述示例,使用flushCache="true"代表需要刷新缓存,在每次调用getUserById查询语句时都会清空缓存从而重新执行SQL查询。
useCache
useCache是Mybatis提供的另一个属性,表示是否使用二级缓存,默认值为true。开启该属性后,Mybatis会先检查是否有缓存可用,如果有,则直接返回结果,否则才会执行SQL语句。
例如:
<select id="getUserById" parameterType="int" resultType="com.example.User" useCache="true">
select * from user where id = #{id}
</select>
上述示例,使用useCache="true"声明需要使用二级缓存,在每次调用getUserById查询时,先从缓存中获取数据,如果没有命中再去查询数据库,查到数据之后会将其放入缓存。注意该特性只对一级缓存有效,如果要使用二级缓存,需配置相应的cache标签。
案例
查询代码测试
@Test
public void query(){
SqlSession sqlSession= MyUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user1 = mapper.getById(1);
System.out.println(user1);
System.out.println("======================");
User user2 = mapper.getById(1);
System.out.println(user2);
sqlSession.close();
}
下面结果可以解释一级缓存默认开启,查询只查了一次
如果关闭了一级缓存,就需要查询两次,如图:
缓存失效的情况:
- 查询不同的语句
- 增删改操作,可能会改变原来的数据,所以必定会刷新缓存
- 手动清理缓存
查询和插入代码测试
@Test
public void query(){
SqlSession sqlSession= MyUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user1 = mapper.getById(1);
int i = mapper.addUser(new User(9, "jdasi", "21423"));
if(i>0){
System.out.println("插入成功");
}
System.out.println("======================");
System.out.println(user1);
sqlSession.close();
}
当分别执行查询和插入,执行两次,此时缓存失效
如果需要开启二级缓存,在sql映射文件添加
<cache/>
如图:
如果遇到下面的问题
在需要在实体类实现一个序列化接口即可