skip to Main Content

I’m trying to caching jpa entity to redis through @Cacheable annotation.

[RedisConfig.class]
@Configuration
public class RedisConfig {
    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory(host, port);
    }

    @Bean
    public RedisTemplate<?, ?> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        return redisTemplate;
    }
}
[Service layer]
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class RoomQueryService {
    private final RoomRepository roomRepository;

    @Cacheable(value = "search", key = "#code")
    public Room searchRoomByCode(String code) {
        return roomRepository.findByCode(code).orElseThrow(RoomNotFoundException::new);
    }
}

When executed above code, it throw below error.

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.data.redis.serializer.SerializationException: Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [slido.slidoclone.room.domain.Room]] with root cause

Maybe it caused because DefaultSerializer can’t serialize jpa entity class.

So I added below 2 lines to RedisConfig.

        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

But it throw same error.

After searching about it, I found 2 solutions.

  1. Add implements Serializable to JPA entity
  2. Use cacheManager in @Cacheable annotation

I’m curious as to which method is used in production.

Thanks.

2

Answers


  1. I think your RedisTemplate isn’t actually used anywhere. You’d have to supply a RedisCacheConfiguration instead (taken from "Spring Boot Cache with Redis"):

    @Bean
    public RedisCacheConfiguration cacheConfiguration() {
        return RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(60))
                .disableCachingNullValues()
                .serializeValuesWith(SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
    }
    
    Login or Signup to reply.
  2. Add annotation @EnableCaching and see the effect.

    @Service
    @RequiredArgsConstructor
    @Transactional(readOnly = true)
    @EnableCaching
    public class RoomQueryService {
    private final RoomRepository roomRepository;
    
    @Cacheable(value = "search", key = "#code")
    public Room searchRoomByCode(String code) {
        return 
      roomRepository.findByCode(code).orElseThrow(RoomNotFoundException::new);
      }
     }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search