无法将对象转换为实体类型
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 类型