qinfengge

qinfengge

醉后不知天在水,满船清梦压星河
github
email
telegram

Cache in Spring Boot

Caching is usually used to speed up frequently used data in the database. In most cases, we use Redis to cache hot data from the MySQL database.

EnableCaching#

Using caching in Spring Boot is relatively simple. First, add the dependency:

<!-- Cache dependency -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

Enable caching support in the main class:

@SpringBootApplication
@EnableCaching

Specify the use of Redis cache in the configuration file. If not specified, JVM memory will be used:
Before using Redis for caching, you need to correctly configure the connection information for Redis

# Caching
spring.cache.type=redis
# Specify prefix
# spring.cache.redis.key-prefix=test
# Specify time-to-live
# spring.cache.redis.time-to-live= 1d

Finally, add the @EnableCaching annotation and cache manager in the Redis configuration class:

/**
 * Declare the cache manager, which will create an aspect and trigger the pointcut of Spring cache annotation based on the annotations and cache status used by the class or method.
 * Based on the annotations used by the class or method and the cache status, this aspect will retrieve data from the cache, add data to the cache, or remove a value from the cache.
 *
 * @return
 */
@Bean
@SuppressWarnings("all")
public CacheManager cacheManager(RedisConnectionFactory factory) {
    RedisSerializer<String> redisSerializer = new StringRedisSerializer();
    Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    // Solve the problem of query cache conversion exception
    ObjectMapper om = new ObjectMapper();
    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    jackson2JsonRedisSerializer.setObjectMapper(om);

    // Configure serialization (solve garbled characters)
    RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofDays(1))
            .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
            .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
            .disableCachingNullValues();

    return RedisCacheManager.builder(factory)
            .cacheDefaults(config)
            .build();
}

Cache Annotations#

Cache AnnotationExplanation
@EnableCachingEnable support for cache annotations
@CacheConfigUsed to specify unified configuration parameters
@CacheableIf there is cached data, return the cached data; otherwise, execute the method and cache the result
@CachePutCache the result based on the method's request parameters; unlike @Cacheable, it always triggers the actual method invocation
@CacheEvictClear the cache based on certain conditions
@CachingCombine multiple cache annotations

@CacheConfig#

This annotation is commonly used to configure unified cache parameters.

// Use this annotation in the controller to specify the cache name, similar to a prefix
@CacheConfig(cacheNames = "test")

@Cacheable#

This annotation is commonly used in query methods. After using this annotation, it will first check the cache. If the cache is empty, it will query from the database and store the result in the cache.

Mermaid Loading...

image

// If the global cacheName/value of @CacheConfig is configured, it can be omitted here
@Cacheable(value = "test", key = "methodName")
// @Cacheable supports EL expressions
@Cacheable(key = "methodName + ':' + #p0 + ':' + #p1")
public Result<Object> getSubordinateAddress(String province,String city){}
@Cacheable(value="users", key="#user.id")
public User find(User user) {}

The key attribute supports the following properties:

Attribute NameDescriptionExample
methodNameCurrent method name#root.methodName
methodCurrent method#root.method.name
targetCurrently called object#root.target
targetClassClass of the currently called object#root.targetClass
argsArray of current method parameters#root.args[0]
cachesCache used by the currently called method#root.caches[0].name

@CachePut#

This annotation is commonly used to update the cache. It ignores the value in the cache and always executes the method.
Execution order: Call the method -> Get the result -> Update the cache

Mermaid Loading...
@CachePut(value = "myCache", key = "#entity.id")
public void saveEntity(MyEntity entity) {
    repository.save(entity);
}

@CacheEvict#

This annotation is used to delete the corresponding cache.

image

@CacheEvict(value = "myCache", key = "#id")
public void deleteEntityById(Long id) {
    repository.deleteById(id);
}

When using allEntries=true, the key is ignored and all values in the specified cacheName/value are cleared.
You can also use the cacheManager object to delete a specific cache. The following code clears the test cache when it is not empty:

Objects.requireNonNull(restTemplateConfig.cacheManager(null).getCache("test")).clear();

@Caching#

This annotation is used to combine multiple cache annotations.

image

@Caching(
    cacheable = {
        @Cacheable(value = "myCache", key = "#id")
    },
    evict = {
        @CacheEvict(value = "otherCache", key = "#id")
    }
)
public MyEntity getEntityById(Long id) {
    return repository.findById(id).orElse(null);
}

The calling sequence is as follows:

Mermaid Loading...

The Correct Way to Use Cache in Spring Boot Projects!!
Spring Boot Cache Management @EnableCaching, @Cacheable

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.