SpringBoot integrates the use of @Cacheable, @CachePut, and @CacheEvict annotations of Redis

This article operates the database, using mybatis-plus. For environment setup, please check the blog post
https://blog.csdn.net/qq_41712271/article/details/115756865

1 Add maven dependency

        <!--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 Configure the RedisConfig class of redis

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, 存储二进制字节码, 所以自定义序列化类 * 开启缓存配置,设置序列化 */@[email protected] 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 Business processing writing, the core class of cache operation

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; @[email protected](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 Writing test classes

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);    }}

Detailed description

#### @CacheConfig
@CacheConfig is a class-level annotation that unifies all cache prefixes of this class.
```  
@CacheConfig(cacheNames = {"user" })
public class UserService { ```The above code represents that all caches of this class can be prefixed with "user::"

#### @Cacheable
@Cacheable is a method-level annotation, used to cache the result of a method .
```  
@Cacheable(key="#id")
public User findUserById(Integer id){      return this.userMapper.selectByPrimaryKey(id); } ```When the above method is called, first read the data from the cache, if The cache does not find the data, and then executes the method body, and finally adds the return value to the cache.



Note: @Cacheable is generally used together with @CacheConfig.
For example, the above @CacheConfig(cacheNames = {"user" }) and @Cacheable(key="#id") are used together.
Call the method to pass in id=100, then the key=user::100 corresponding to redis, and the value is serialized to json by using GenericJackson2JsonRedisSerializer to
call id=200, then the key=user::200 corresponding to redis, and the value is by using GenericJackson2JsonRedisSerializer Serialize to json

#### @CachePut
@CachePut is a method-level annotation, used to update the cache .
```  
@CachePut(key = "#obj.id")
public User updateUser(User obj){      this.userMapper.updateByPrimaryKeySelective(obj);      return this.userMapper.selectByPrimaryKey(obj.getId()); } ``` When the above method is called, the method body is executed first, and then springcache updates the cache by the return value, that is, key = "#obj.id", value=User




#### @CacheEvict(key = "#id")
@CachePut is a method-level annotation, used to delete the cache .
```  
public void deleteUser(Integer id){      User user=new User();      user.setId(id);      user.setDeleted((byte)1);      this.userMapper.updateByPrimaryKeySelective(user); } ``` above When the method is called, the method body is executed first, and the cache is deleted through the method parameters







### The big pit of springcache

1. For redis cache, springcache only supports String , other Hash, List, set, ZSet do not support,
   so for Hash, List, set, ZSet can only use RedisTemplate
   
2. For multi-table query data cache, springcache is If it is not supported, only a simple cache of a single table is supported .
   For the overall cache of multiple tables, only RedisTemplate can be used.