二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。
1.添加pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
2.添加redis配置类
@Configuration
public class RedisConfig {
@Value("${spring.redis.host}")
private String host;
@Bean
public JedisPoolConfig getRedisConfig(){
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(maxIdle);
config.setMaxTotal(maxTotal);
config.setMaxWaitMillis(maxWaitMillis);
config.setMinIdle(minIdle);
return config;
}
@Bean(name = "jedisConnectionFactory")
public JedisConnectionFactory getConnectionFactory(){
JedisConnectionFactory factory = new JedisConnectionFactory();
JedisPoolConfig config = getRedisConfig();
factory.setPoolConfig(config);
factory.setHostName(host);
factory.setPort(port);
factory.setDatabase(database);
factory.setPassword(password);
factory.setTimeout(timeout);
return factory;
}
@Bean(name = "redisTemplate")
public RedisTemplate<?, ?> getRedisTemplate(){
RedisTemplate<?,?> template = new StringRedisTemplate(getConnectionFactory());
return template;
}
}
3.在application.properties中配置redis
## Redis 配置
## Redis数据库索引(默认为0)
spring.redis.database=0
## Redis服务器地址
spring.redis.host=127.0.0.1
## Redis服务器连接端口
spring.redis.port=6379
## Redis服务器连接密码(默认为空)
spring.redis.password=
## 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
## 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
## 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
## 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
## 连接超时时间(毫秒)
spring.redis.timeout=0
4.配置Redis作为Mybatis的缓存
public class MybatisRedisCache implements Cache {
private static JedisConnectionFactory jedisConnectionFactory;
private static JedisPool pool;
private final String id;
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public MybatisRedisCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
this.id = id;
pool = new JedisPool(jedisConnectionFactory.getPoolConfig(), jedisConnectionFactory.getHostName(), jedisConnectionFactory.getPort());
}
private Object execute(RedisCallback callback) {
Jedis jedis = pool.getResource();
Object var3;
try {
var3 = callback.doWithRedis(jedis);
} finally {
jedis.close();
}
return var3;
}
@Override
public String getId() {
return this.id;
}
@Override
public int getSize() {
return (Integer) this.execute(new RedisCallback() {
@Override
public Object doWithRedis(Jedis jedis) {
Map<byte[], byte[]> result = jedis.hgetAll(MybatisRedisCache.this.id.toString().getBytes());
return result.size();
}
});
}
@Override
public void putObject(final Object key, final Object value) {
this.execute(new RedisCallback() {
@Override
public Object doWithRedis(Jedis jedis) {
jedis.hset(MybatisRedisCache.this.id.toString().getBytes(), key.toString().getBytes(), SerializeUtil.serialize(value));
return null;
}
});
}
@Override
public Object getObject(final Object key) {
return this.execute(new RedisCallback() {
@Override
public Object doWithRedis(Jedis jedis) {
return SerializeUtil.unserialize(jedis.hget(MybatisRedisCache.this.id.toString().getBytes(), key.toString().getBytes()));
}
});
}
@Override
public Object removeObject(final Object key) {
return this.execute(new RedisCallback() {
@Override
public Object doWithRedis(Jedis jedis) {
return jedis.hdel(MybatisRedisCache.this.id.toString(), new String[]{key.toString()});
}
});
}
@Override
public void clear() {
this.execute(new RedisCallback() {
@Override
public Object doWithRedis(Jedis jedis) {
jedis.del(MybatisRedisCache.this.id.toString());
return null;
}
});
}
@Override
public ReadWriteLock getReadWriteLock() {
return this.readWriteLock;
}
@Override
public String toString() {
return "Redis {" + this.id + "}";
}
public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
MybatisRedisCache.jedisConnectionFactory = jedisConnectionFactory;
}
}
5.通过RedisCacheTransfer静态注入
@Component
public class RedisCacheTransfer {
@Autowired
public void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
MybatisRedisCache.setJedisConnectionFactory(jedisConnectionFactory);
}
}
6.配置mapper作用域namespace
二级缓存的作用域是mapper的namespace,所以要在mapper中添加这句话
<cache type="com.kangaroo.studio.moonlight.dao.cache.MybatisRedisCache"/>
7.实现model序列化
读写缓存Model需要序列化,只需要在类声明的时候 implements Serializable 就好了。
8.配置logback.xml,控制台查看sql语句
总结:
在第一次查询的时候,可以在控制台看到查询的sql语句,当再次进行查询的时候,控制台不再输出sql语句,此时数据是从redis缓存中获取的。