【问题标题】:Hibernate returns proxy for base classHibernate 返回基类的代理
【发布时间】:2017-12-25 22:20:42
【问题描述】:

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

@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,而不是正确的子类(它的类是BaseEntity_$$_jvsted9_26,因此entity instanceof IndividualEntity是假的)。

有趣的是,并非所有对象都作为代理返回。
我在循环中获取实体(普通事务),其中一些以正常形式返回(即IndividualEntity/BranchEntity),一些作为代理返回。
如果我更改机制,以便每次提取都在单独的事务中完成 - 根本不会返回任何代理对象。

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

【问题讨论】:

标签: java hibernate orm spring-data-jpa


【解决方案1】:

如果没有看到更多的对象模型就无法确定,但 Hibernate 会这样做的一个原因是,如果 BaseEntity 在会话的早些时候已经被解析为同一 BaseEntity.id 的代理。

例如,如果有另一个类与 BaseEntity 有 ToOne 关系,那么它将只有一个指向 id 的外键,因此将使用 BaseEntity_$$... 代理来延迟解析正确的子类另一端。这将成为在 Hibernate PersistenceContext 中管理的 id 的实例。

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

【讨论】:

  • 是的,这听起来很合理!我已经使用访客模式处理了这个问题,顺便说一句。感谢您提供此信息!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-14
相关资源
最近更新 更多