我正在尝试使用 Redis 缓存来提高我们应用程序的性能。我指的是这个 article对于我的实现。我收到此异常:
class com.entity.UserEntity cannot be cast to class com.entity.UserEntity
Redis配置:@Configuration
@EnableCaching
public class RedisConfig {
@Value("${spring.redis.port}") int redisPort;
@Value("${spring.redis.host}") String redisHost;
@Bean
public LettuceConnectionFactory redisLettuceConnectionFactory() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(redisHost,redisPort);
return new LettuceConnectionFactory(redisStandaloneConfiguration);
}
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisLettuceConnectionFactory());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new JdkSerializationRedisSerializer());
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
redisTemplate.setEnableTransactionSupport(true);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
用户实体:@Entity
@Getter
@Setter
@EqualsAndHashCode(callSuper=false)
@Slf4j
@Table(name="user")
public class UserEntity extends BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "user_id")
@Type(type = "uuid-char")
private UUID userId;//Binary in DB and UUID here
@OneToMany(fetch = FetchType.EAGER, mappedBy = "user", orphanRemoval = true, cascade= CascadeType.ALL)
@JsonIgnore
@ToStringExclude
@Fetch(value = FetchMode.SUBSELECT)
private List<EmailAddress> emailAddresses = new ArrayList<>();
.
.
.
}
用户道Impl@Repository
public class UserDaoImpl implements UserDao {
private UserRepository userRepository;
private HashOperations hashOperations; //to access Redis cache
private static final String KEY = "User";
public UserDaoImpl(@Autowired RedisTemplate<String, Object> redisTemplate, @Autowired UserRepository userRepository) {
this.userRepository = userRepository;
hashOperations = redisTemplate.opsForHash();
}
@Override
public Optional<UserEntity> fetchUserById(String userId) throws Exception {
// Getting Exception here (UserEntity) hashOperations.get(KEY,userId)
UserEntity userEntity = (UserEntity) hashOperations.get(KEY,userId);
Optional<UserEntity> userOptional = Optional.ofNullable(userEntity);
if(!userOptional.isPresent()) {
userOptional = userRepository.findByUserId(userId);
if (userOptional.isPresent()) {
System.out.println("Cache Miss User id:" + userOptional.get().getUserId());
hashOperations.put(KEY, userOptional.get().getUserId().toString(), userOptional.get());
} else {
throw new Exception("User not present");
}
}
return userOptional;
}
}
我能够成功地将 UserEntity 放入缓存中,但是在检索时我得到了上面提到的异常。最有可能的问题是由于 Hibernate。当我们第一次缓存实体时,它会用 Proxy/PersistentBag 代替 Collections,所以下次(在其他 session 中)当我们从缓存中检索对象时,我们无法将其转换为所需的实体。有人可以确认这是问题所在,如果是,如何解决?
最佳答案
Hibernate 装饰了类,这可能是导致问题的原因,另外还有对底层数据库的重量级引用。
我强烈建议(无论您是否使用 Redis)定义一个 POJO实体的版本并尽早将实体类转换为 POJO,并尽可能晚地将 POJO 转换为实体,以便您的应用程序处理 POJO,并接收、验证和发出(从其 API)POJO,以及该实体仅在与数据库交互时使用。
在 Redis 中存储 POJO 实例而不是实体实例。
或者为了更健壮,将您的 POJO 序列化为 json 并将 json 字符串存储在 redis 中,在返回的途中将其反序列化。 Jackson(与 spring boot 一起免费提供,支持开箱即用。实现起来 super 简单,而且您可以通过目视检查内容轻松调试 Redis 中的内容。
关于java - 无法将对象转换为实体类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70297666/