1.一级缓存
缓存相关信息可在:
Mybatis 默认存在一级缓存:查询一次后 会将结果存在本地
总结:Mybatis自带一级缓存 , 一级缓存会在更新 ,删除,修改,提交事务后 清除缓存;一级缓存返回的是同一对象
一级缓存源码:
在BaseExecutor的Query方法中调用了 createCacheKey 创建缓存
2.二级缓存
二级缓存不是默认开启的 ,需要在Config.xml文件中手动开启。
二级缓存是全局的 ,不是对于某一方法的。 开启二级缓存后会对 整个mapper中的 方法生效。
二级缓存不属于任何一个对象,所有对于同一个Mapper文件的Sqlsession对象共同拥有
因为二级缓存的数据是通过序列化、反序列化存储和拿取的所以查询对象想要使用二级缓存需要实现序列化
也就是实现Serializable接口
没有开启二级缓存的效果:会多次向数据库发起请求缓存集中率为0
二级缓存的开启(自带二级缓存): !!!因为二级缓存是事务性查询缓存机制 每个会话需要关闭或提交后 才会把查询结果放在二级缓存中
注意!!!如果在Sqlsession中是自动提交需要将会话关闭后查询结果才会放在缓存中
需要在SqlConfig全局配置文件中配置
<configuration> <settings> <setting name="cacheEnabled" value="true"/> </settings> </configuration>
在Mapper映射文件中配置
<cache/>
开启后的效果:只会像数据库发起一次请求,第二次会从二级缓存中拿取
总结:二级缓存是事务性缓存,会话需要关闭后才会将数据放入缓存中,与一级缓存一样在更新删除修改后 刷新缓存,二级缓存不像一级缓存一样存放同一对象,二级缓存是储存查询到的数据,你需要时再封装成对象进行赋值
拓展二级缓存开启:
1.为什么要使用其他的缓存? Mybatis默认的是
默认是是不支持分布式缓存的,所以要引入第三方缓存;(要实现自定义缓存 只需要 实现Cache接口就行了)
2.开启第三方二级缓存(redis):
可参考网站 mybatis-redis – MyBatis Redis | Reference Documentation
2.1首先加入Mybatis整合Redis依赖:
<dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-redis</artifactId> <version>1.0.0-beta2</version> </dependency>
2.2在Mapper映射文件中配置:
<mapper namespace="。。。。。"> <cache type="org.mybatis.caches.redis.RedisCache" /> </mapper>
2.3在类路径文件下配置redis.properties(必须叫这个名字不能叫别的)文件:
redis.host=localhost //链接地址 redis.port=6379 //连接端口号 redis.connectionTimeout=5000 超时时间 redis.password= 密码为空 redis.database=0 // 连接哪个数据库
3.Redis-MyBatisCache源码分析:
3.1 如果没有在类文件下创建redis.properties文件RedisConfig中提供了默认配置:
3.2 redis配置文件加载流程:(解释了为什么配置文件必须叫redis.properties)
//这里就是redis配置文件的名字也解释了配置文件为什么要叫这个名字 private static final String REDIS_RESOURCE = "redis.properties"; private final String redisPropertiesFilename; private RedisConfigurationBuilder() { //将redis配置文件名赋值给redisPropertiesFilename redisPropertiesFilename = System.getProperty(SYSTEM_PROPERTY_REDIS_PROPERTIES_FILENAME, REDIS_RESOURCE); } public RedisConfig parseConfiguration(ClassLoader classLoader) { Properties config = new Properties(); //解析redis配置文件 InputStream input = classLoader.getResourceAsStream(redisPropertiesFilename); if (input != null) { try { config.load(input); } catch (IOException e) { throw new RuntimeException( "An error occurred while reading classpath property '" + redisPropertiesFilename + "', see nested exceptions", e); } finally { try { input.close(); } catch (IOException e) { // close quietly } } } RedisConfig jedisConfig = new RedisConfig(); setConfigProperties(config, jedisConfig); return jedisConfig; }
3.3 缓存的创建与查询
在redisCache中: