【问题标题】:Spring boot Cacheable annotation with JPA entity带有 JPA 实体的 Spring Boot Cacheable 注释
【发布时间】:2021-10-28 10:30:44
【问题描述】:

我正在尝试通过@Cacheable 注解将jpa 实体缓存到redis。

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

当执行上面的代码时,它会抛出下面的错误。

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

可能是因为 DefaultSerializer 无法序列化 jpa 实体类造成的。

所以我在 RedisConfig 中添加了以下 2 行代码。

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

但它会抛出同样的错误。

搜索了一下,找到了2个解决方案。

  1. implements Serializable 添加到JPA 实体
  2. @Cacheable注解中使用cacheManager

我很好奇生产中使用了哪种方法。

谢谢。

【问题讨论】:

标签: java spring spring-boot jpa


【解决方案1】:

我认为您的RedisTemplate 实际上并没有在任何地方使用。您必须提供 RedisCacheConfiguration 代替(取自 "Spring Boot Cache with Redis"):

@Bean
public RedisCacheConfiguration cacheConfiguration() {
    return RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMinutes(60))
            .disableCachingNullValues()
            .serializeValuesWith(SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
}

【讨论】:

    【解决方案2】:

    添加注解@EnableCaching,看看效果。

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

    【讨论】:

      猜你喜欢
      • 2017-05-22
      • 2020-07-04
      • 2012-07-08
      • 1970-01-01
      • 2020-01-20
      • 1970-01-01
      • 2018-03-22
      • 2019-03-31
      • 2022-01-02
      相关资源
      最近更新 更多