Hibernate返回基类的代理

时间:2017-07-20 09:40:13

标签: java hibernate orm spring-data-jpa

我的域模型中有一个层次结构,由类描述:

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class BaseEntity {
    @Id
    private Long id;

    // other fields
}

@DiscriminatorValue(value = "Individual")
public class IndividualEntity extends BaseEntity {
    // fields
}

@DiscriminatorValue(value = "Branch")
public class BranchEntity extends BaseEntity {
    // fields
}

我正在抓取这样的对象:

Specification<BaseEntity> specification = createSpecification();
BaseEntity entity = baseRepository.findOne(specification);

(我使用的是弹簧数据)

问题是Hibernate返回代理对象(我理解的),但代理是BaseEntity,而不是正确的子类(它的&#39;类是BaseEntity_$$_jvsted9_26,因此{{1}是假的。

有趣的是,并非所有对象都作为代理返回 我在循环中获取实体(常见事务),其中一些以正常形式返回(即entity instanceof IndividualEntity / IndividualEntity),一些作为代理返回。
如果我改变机制,那么每次获取都在单独的事务中完成 - 根本不返回代理对象。

我知道我可以解开那个代理(例如像here),但这种行为的原因是什么(对我来说有点奇怪),我可以避免吗?

1 个答案:

答案 0 :(得分:4)

不能确定没有看到更多的对象模型,但是Hibernate这样做的原因之一是,是否必须在会话开始时已将BaseEntity解析为同一BaseEntity.id的代理。 / p>

例如,如果存在另一个与BaseEntity具有ToOne关系的类,则它将仅具有id的外键,因此将使用BaseEntity_$$...代理来延迟为另一端解析正确的子类。然后,这成为在休眠id中管理的PersistenceContext的实例。

很显然,Hibernate.unwrap()或上面链接中的其他选项之一将显示'true'实例。另一种选择是在BaseEntity(例如isIndividual())上使用抽象方法。这看起来可能比较整洁,但是最终,在调用该方法时,Hibernate仍然需要解析代理。