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.
- Add
implements Serializable
to JPA entity - Use cacheManager in
@Cacheable
annotation
I'm curious as to which method is used in production.
Thanks.
CodePudding user response:
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()));
}
CodePudding user response:
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);
}
}