一级缓存
mybatis中一级缓存也叫做本地缓存,一级缓存是在会话也就是SqlSession层面实现的,一级缓存的作用范围是在同一个SqlSession中,不同的SqlSession即使查询相同的数据也不会走缓存。
一级缓存如何开启
一级缓存默认是开启的
一级缓存范围
mybatis一级缓存的范围有SESSION和STATEMENT两种,默认是SESSION。 如果不想使用一级缓存,可以把一级缓存的范围指定为STATEMENT,这样每次执行完一个Mapper中的语句后都会将一级缓存清除。 如果需要更改一级缓存的范围,可以在Mybatis的配置文件中,通过localCacheScope指定。
<setting name="localCacheScope" value="STATEMENT"/>
一级缓存命中原则?/mybatis怎么判断某两次查询是完全相同的查询?
条件1:要求查询的StatementId必须相同,否则无法命中缓存,即使两个查询语句、参数等完全一样。
条件2:要求传递给SQL的查询参数必须相同,否则无法命中缓存
条件3:要求分页参数必须相同,否则无法命中缓存
条件4:要求传递给JDBC的SQL必须完全相同
条件5:要求执行的环境相同:比如测试环境、生产环境
构成以上五个条件的代码逻辑:
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
if (closed) {
throw new ExecutorException("Executor was closed.");
}
CacheKey cacheKey = new CacheKey();
cacheKey.update(ms.getId()); // 条件1 Mapper Id 例子:com.blog4java.mybatis.example.mapper.UserMapper.listAllUser
cacheKey.update(rowBounds.getOffset()); // 偏移量 (分页参数) 条件3
cacheKey.update(rowBounds.getLimit()); // 条数 (分页参数) 条件3
cacheKey.update(boundSql.getSql()); // 条件4 SQL语句
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
//条件2 所有参数值
for (ParameterMapping parameterMapping : parameterMappings) {
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) {
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
cacheKey.update(value);
}
}
// Environment Id 条件5
if (configuration.getEnvironment() != null) {
cacheKey.update(configuration.getEnvironment().getId());
}
return cacheKey;
}
一级缓存什么时候销毁?
- 在执行SqlSession.commit()之后,缓存会被清空,第二次查询会查询数据库
2. 在执行SqlSession.rollback()之后,缓存会被清空,第二次查询会查询数据库
3. 在执行insert、update、delete操作之后,缓存会被清空,第二次查询会查询数据库
4. 在执行SqlSession.clearCache之后,缓存会被清空,第二次查询会查数据库
5、SqlSession关闭,即执行SqlSession.close()方法会清空缓存
一级缓存工作原理
一级缓存是Mybatis中默认开启的缓存,它是在SqlSession的生命周期内有效的,也就是说,当我们从SqlSessionFactory中获取SqlSession对象,执行SQL语句后,查询到的结果会被缓存到该SqlSession对象的缓存中。当我们再次执行相同的SQL语句时,Mybatis会先从缓存中查找结果,如果存在则直接返回缓存中的数据,否则再去数据库中查询。 Mybatis的一级缓存是基于HashMap实现的,缓存的Key是SQL语句以及该语句所使用的参数,缓存的value是查询到的结果集。当我们执行查询语句时,Mybatis会先在缓存中查找是否存在相同的key,如果存在,则直接返回缓存中的value,否则再去执行SQL语句。当我们修改或删除数据时,Mybatis会自动将该SqlSession对象的缓存清空,以避免数据不一致的问题。 一级缓存是基于SqlSession对象实现的,因此,当我们执行多个SqlSession对象时,每个SqlSession对象都会有自己的一级缓存,它们之间互不干扰。这也意味着,如果我们执行了多个SqlSession对象,且每个对象执行了相同的查询语句,那么每个SqlSession对象都会去数据库中查询数据,而不会从其他SqlSession对象的缓存中获取数据。
二级缓存
二级缓存是Mapper级别的缓存,需要在Mybatis的配置文件中进行配置
二级缓存开启
开启二级缓存需要在mybatis-config.xml中配置:
<setting name="cacheEnabled" value="true"/>
二级缓存命中原则
同一级缓存命中原则
二级缓存清除
当执行增删改方法时会清除缓存
自定义缓存(redis实现)
这种缓存多用于分布式环境下使用,它通常借助于外部的分布式缓存系统,如redis或Memcached。这种缓存机制可以跨足多个应用服务器,实现分布式缓存共享。
使用mybatis整合redis实现分布式缓存
- pom坐标
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-redis</artifactId>
<version>1.0.0-beta2</version>
</dependency>
- application.properties 中配置
# 开启缓存
mybatis-plus.configuration.cache-enabled=true
##redis 配置
redis.host=localhost
redis.port=6379
redis.connectionTimeout=5000
redis.password=
redis.database=0
- mapper.xml 文件中
<cache type="org.mybatis.caches.redis.RedisCache"/>