无法将对象转换为实体类型

Posted

技术标签:

【中文标题】无法将对象转换为实体类型【英文标题】:Unable to cast the Object to Entity Type 【发布时间】:2022-01-14 17:48:24 【问题描述】:

我正在尝试使用 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<>();
   .
   .
   .

UserDaoImpl

@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 代替集合,因此下一次(在其他会话中)当我们从缓存中取回对象时,我们无法将其转换为所需的实体。有人可以确认这是问题所在,如果是,如何解决?

【问题讨论】:

【参考方案1】:

Hibernate 装饰了这个类,这可能是导致问题的原因,另外还有对底层数据库的重量级引用。

我强烈建议(无论您是否使用 Redis)定义您的实体的 POJO 版本并尽可能尽早将实体类转换为 POJO,并将 POJO 转换为实体尽可能延迟,因此您的应用程序处理 POJO,并(从其 API)接收、验证和发出 POJO,并且该实体在与数据库。

将 POJO 实例存储在 Redis 中而不是实体实例中。

或者为了更健壮,将您的 POJO 序列化为 json 并将 json 字符串存储在 redis 中,然后在返回时将其反序列化。 Jackson(随 Spring Boot 免费提供,开箱即用。实现起来非常简单,另外您可以通过目视检查 Redis 的内容轻松调试 Redis 中的内容。

【讨论】:

以上是关于无法将对象转换为实体类型的主要内容,如果未能解决你的问题,请参考以下文章

无法将 java.lang.Boolean 类型的对象转换为类型

无法将 java.lang.String 类型的对象转换为类型 - FirebaseUI

无法将类型为“System.DateTime”的对象强制转换为类型“System.String”

无法将 Person 类型的对象转换为 PersonViewModel 类型

无法将 java.lang.String 类型的对象转换为 com.example 类型

无法将“System.Object[]”类型的对象转换为“MyObject[]”,这是啥原因?