本文操作数据库,使用的是mybatis-plus,关于环境搭建,可查看博文
https://blog.csdn.net/qq_41712271/article/details/115756865
1 添加maven依赖
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--spring cache-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!--spring cache连接池依赖包-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.6.2</version>
</dependency>
2 配置redis的RedisConfig类
package cn.jiqistudy.redis_1.Config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.*;
import java.time.Duration;
/**
* redisTemplate 序列化使用的jdkSerializeable, 存储二进制字节码, 所以自定义序列化类
* 开启缓存配置,设置序列化
*/
@Configuration
@EnableCaching
public class RedisConfig {
@Primary
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory){
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
redisCacheConfiguration = redisCacheConfiguration
//设置缓存的默认超时时间:30分钟
.entryTtl(Duration.ofMinutes(30L))
//如果是空值,不缓存
.disableCachingNullValues()
//设置key序列化器
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
//设置value序列化器
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()));
return RedisCacheManager
.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
.cacheDefaults(redisCacheConfiguration)
.build();
}
/**
* key序列化器
*/
private RedisSerializer<String> keySerializer() {
return new StringRedisSerializer();
}
/**
* value序列化器
*/
private RedisSerializer<Object> valueSerializer() {
return new GenericJackson2JsonRedisSerializer();
}
}
3 业务处理编写,缓存操作的核心类
package cn.jiqistudy.redis_1.service;
import cn.jiqistudy.redis_1.mapper.UserMapper;
import cn.jiqistudy.redis_1.pojo.User;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
@CacheConfig(cacheNames = { "user" })
public class UserService {
private static final Logger LOGGER = LoggerFactory.getLogger(UserService.class);
@Resource
private UserMapper userMapper;
//新增缓存,注意方法的返回值
@Cacheable(key="#id")
public User findUserById(Integer id){
return this.userMapper.selectById(id);
}
//更新缓存,注意方法的返回值
@CachePut(key = "#obj.id")
public User updateUser(User obj){
this.userMapper.updateById(obj);
return this.userMapper.selectById(obj.getId());
}
//删除缓存
@CacheEvict(key = "#id")
public void deleteUser(Integer id){
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
userQueryWrapper.eq("id",id);
this.userMapper.delete(userQueryWrapper);
}
}
4 测试类编写
import cn.jiqistudy.redis_1.Redis1Application;
import cn.jiqistudy.redis_1.pojo.User;
import cn.jiqistudy.redis_1.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Redis1Application.class)
public class Test_7 {
@Autowired
private UserService userService;
//将查询的结果,缓存起来
@Test
public void fangfa1()
{
User userById = userService.findUserById(2);
System.out.println(userById);
}
//同时更新数据库和缓存
@Test
public void fangfa2()
{
User user = new User(2,"李盛霖","男1",15,"地球");
userService.updateUser(user);
}
//同时删除数据库记录和缓存
@Test
public void fangfa3()
{
userService.deleteUser(1);
}
}
详细说明
#### @CacheConfig
@CacheConfig是类级别的注解,统一该类的所有缓存前缀。
```
@CacheConfig(cacheNames = { "user" })
public class UserService {
```
以上代码,代表了该类的所有缓存可以都是"user::"为前缀
#### @Cacheable
@Cacheable是方法级别的注解,用于将方法的结果缓存起来。
```
@Cacheable(key="#id")
public User findUserById(Integer id){
return this.userMapper.selectByPrimaryKey(id);
}
```
以上方法被调用时,先从缓存中读取数据,如果缓存没有找到数据,再执行方法体,最后把返回值添加到缓存中。
注意:@Cacheable 一般是配合@CacheConfig一起使用的
例如上文的@CacheConfig(cacheNames = { "user" }) 和 @Cacheable(key="#id")一起使用时。
调用方法传入id=100,那redis对应的key=user::100 ,value通过采用GenericJackson2JsonRedisSerializer序列化为json
调用方法传入id=200,那redis对应的key=user::200 ,value通过采用GenericJackson2JsonRedisSerializer序列化为json
#### @CachePut
@CachePut是方法级别的注解,用于更新缓存。
```
@CachePut(key = "#obj.id")
public User updateUser(User obj){
this.userMapper.updateByPrimaryKeySelective(obj);
return this.userMapper.selectByPrimaryKey(obj.getId());
}
```
以上方法被调用时,先执行方法体,然后springcache通过返回值更新缓存,即key = "#obj.id",value=User
#### @CacheEvict(key = "#id")
@CachePut是方法级别的注解,用于删除缓存。
```
public void deleteUser(Integer id){
User user=new User();
user.setId(id);
user.setDeleted((byte)1);
this.userMapper.updateByPrimaryKeySelective(user);
}
```
以上方法被调用时,先执行方法体,在通过方法参数删除缓存
### springcache的大坑
1. 对于redis的缓存,springcache只支持String,其他的Hash 、List、set、ZSet都不支持,
所以对于Hash 、List、set、ZSet只能用RedisTemplate
2. 对于多表查询的数据缓存,springcache是不支持的,只支持单表的简单缓存。
对于多表的整体缓存,只能用RedisTemplate。