【问题标题】:Getting sub-classes from EntityManager.find()从 EntityManager.find() 获取子类
【发布时间】:2016-04-06 05:05:12
【问题描述】:

我有一个可以子类化的JPA实体,定义如下:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "IDTYPE",
    discriminatorType = DiscriminatorType.STRING,
    length = 12)
public class BaseObject implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    //etc

这样做的好处是 BaseObject 和它的所有子类共享相同的 ID 字段——每个值对于它们都是唯一的。我的问题是当我像这样在基类上执行 EntityManager.find() 时:

@PersistenceContext protected EntityManager em;

//  find a record.

BaseObject obj = em.find(BaseObject.class, longIDValue);

如果 find 方法使用该特定 ID,它会返回其中一个子类吗?还是它总是只返回一个 BaseClass 对象?

后续问题:这种行为在不同的 JPA 实现中是否一致? (例如 Hibernate 与 EclipseLink)

【问题讨论】:

  • 当你这样做时会发生什么?当我使用 DataNucleus JPA 执行此操作时,我得到了正确的类型......即可以是子类。就像 JPA 规范一样
  • @NeilStockton 我的应用程序有问题,所以我还没有得到测试。但即使它有效,我也想确保我没有做一些依赖于实现的事情。我在规范中错过了这一点——如果您可以发布指向它的链接,我会将其标记为答案。
  • 您确定想要/需要一个具有联合继承的超级实体吗?这将导致严重的减速,尤其是在 @OneToMany/@ManyToMany 关系上。
  • @MicheleMariotti 用例是这样的:假设 ID 是 URL 的一部分。 servlet 事先并不知道它何时必须获取它所引用的类。它可能是 BaseObject 或某个子类。一旦有了它,我们就可以简单地将 instanceof 用于它需要提供适当响应的任何逻辑。所以是的,我认为我们确实想要指定的行为。
  • 好吧,如果这是您的要求,我认为您是对的,别无选择。即使使用纯 SQL 也想不出更好的办法……

标签: hibernate jpa eclipselink jpa-2.0


【解决方案1】:

EntityManager.find() 返回指定“id”和实体类的类型的实例。如果您有继承并提供超类并且“id”暗示子类的实例,那么这将返回子类(多态性)。向表中添加鉴别器的全部原因是允许实现为您提供此类处理。

find() 的 JPA 规范描述(不是他们费心添加太多描述)没有明确说明这种行为,尽管它必须按照上述方式与基本 JPQL 查询保持一致“ SELECT b FROM BaseClass b" 将返回 SubClass 的实例,其中对象属于该类型。

【讨论】:

    猜你喜欢
    • 2023-03-03
    • 1970-01-01
    • 2013-01-13
    • 2021-12-26
    • 2011-07-07
    • 2014-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多