Java 为什么向下转换在使用quarkus panache的惰性获取时引发异常?
我有一个实体层次结构:Java 为什么向下转换在使用quarkus panache的惰性获取时引发异常?,java,hibernate,jpa,quarkus,quarkus-panache,Java,Hibernate,Jpa,Quarkus,Quarkus Panache,我有一个实体层次结构:ATeamEntity和BTeamEntity,它扩展了BaseTeamEntity和UserEntity,其中包含BaseTeamEntity。 BaseTeamEntity和UserEntity扩展BaseEntity 而BaseEntity扩展了panacheintybase 我在UserEntity中定义了以惰性方式获取BaseTeamEntity 我试着做一个像这样的沮丧的表演: UserEntity user=UserEntity.findById(1L); B
ATeamEntity
和BTeamEntity
,它扩展了BaseTeamEntity
和UserEntity
,其中包含BaseTeamEntity
。
BaseTeamEntity
和UserEntity
扩展BaseEntity
而BaseEntity
扩展了panacheintybase
我在UserEntity
中定义了以惰性方式获取BaseTeamEntity
我试着做一个像这样的沮丧的表演:
UserEntity user=UserEntity.findById(1L);
BaseTeamEntity团队=user.team;
ATeamEntity ateam=(ATeamEntity)团队 当惰性地获取用户的团队时,Hibernate将使用团队的代理(而不是真实的团队对象)填充字段。该代理本质上是由Hibernate动态生成的类的空实例
一旦您将调用团队对象上的方法(例如,getAData()
),Hibernate将通过执行相应的select查询来初始化代理
在执行该查询之前,Hibernate不知道类型(ATeamEntity或BTeamEntity),它只知道它是BaseTeamEntity,因此代理类扩展BaseTeamEntity,强制转换失败
将fetch类型更改为eager时,您要求Hibernate立即获取团队,它不需要创建代理,因为它已经知道该类型
代理的一个优点是,您可能永远不需要访问团队对象,在这种情况下,您需要保存查询。除了@guillome答案之外,我想说的是,要执行代理安全类型转换,您应该执行以下操作:
UserEntity user=UserEntity.findById(1L);
BaseTeamEntity团队=user.team;
ATeamEntity ateam=entityManager.getReference(ATeamEntity.class,team.id);
assertTrue(团队!=ateam);/!!!
长a=ateam.aData;
在调用getReference()
之后,team
和ateam
引用两个不同的代理
实例,这两个实例都委托给相同的基础atementity
实例。但是,第二个代理具有不同的接口,您可以检查仅适用于此接口的ateam.aData
等字段。(请注意,team.getId()
将触发一个SELECT
,如果您将id属性映射为)
java.lang.ClassCastException: class ***.***.entities.team.BaseTeamEntity$HibernateProxy$YcDcMejE cannot be cast to class ***.***.entities.team.ATeamEntity (***.***.entities.team.BaseTeamEntity$HibernateProxy$YcDcMejE and ***.***.entities.team.ATeamEntity are in unnamed module of loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @4f636cba)