是否使用Eclipselink/JPA更改实体类型?

是否使用Eclipselink/JPA更改实体类型?,jpa,inheritance,eclipselink,Jpa,Inheritance,Eclipselink,我知道,但是他们是在Hibernate的范围内被询问和回答的。我也有同样的问题,但我正在使用Eclipselink,想知道对于Hibernate,是否有更好的或替代的解决方案 简单地回顾一下问题: 我有两个相互继承的类: @Entity @Inheritance(strategy=InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name="dtype") @DiscriminatorValue(value="parent") public c

我知道,但是他们是在Hibernate的范围内被询问和回答的。我也有同样的问题,但我正在使用Eclipselink,想知道对于Hibernate,是否有更好的或替代的解决方案

简单地回顾一下问题:

我有两个相互继承的类:

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="dtype")
@DiscriminatorValue(value="parent")
public class Parent {
  @Id
  private long id;
}


@Entity
@DiscriminatorValue(value="child")
public class Child extends Parent{
   private String childProperty;
}
现在我想把孩子变成父母,或者反过来,例如

Parent p = new Parent();
em.persist(p);

Child c = (Child) p;
em.merge(c);
我希望p的数据库行现在是
dtype=child

另一种方式是:

Child c = new Child();
em.persist(c);

Parent c = (Parent) c;
em.merge(c);
在这种情况下,我希望
c
dtype=parent
一起保存,并丢失
childProperty
的值

然而,上面所描述的并不起作用,但我写下来是为了说明我的意思


有没有办法用Eclipselink做到这一点?

如果您想将对象从一种类型“更改”为另一种类型,没有简单的java或JPA继承解决方案。您必须克隆实例,删除旧实例,然后将新实例持久化为符合JPA/Java的:

Child c = em.find(pk, Child.class);
Parent p = new Parent();
p.setId(c.getId());
p.setOtherFields(c.getOtherFields());

em.getTransaction().begin();
em.remove(c);
em.getTransaction().commit();
em.clear();
em.getTransaction().begin();
em.persist(p);
em.getTransaction().commit();
对所有事务使用相同的事务“可能”会使用flush而不是commit/begin,但这并不能保证,因为管理辅助缓存变得很棘手。还请注意,需要更新与子实例的所有关系,以指向“新”父实例,否则缓存将损坏

但我并不确定这一点,因为在本例中,子实例已经是父实例了。通过这种方法,除了数据库中的任意标志外,什么也得不到。如果您希望动态地更改它,那么对于您的应用程序来说,使用Java子类可能不是正确的方法


相反,我建议使用一个通用的Person,该字段可以设置为保持子/父状态。但既然孩子可以同时成为父母..

请用面向对象的方式描述,或给出示例代码,如何理解“更改类型”?我扩展了描述它似乎设计得不自然,在第一步之后,下一步也是错误的。我不能流利地用英语描述如何(据我所知)解决问题1为什么?仅将父对象强制转换为子对象不会改变对象本身中的任何内容。Java对象不会变形——您创建一个Java对象的实例,它仍然是这样。如果您需要一个子对象成为父对象,您可以创建一个新的父对象实例——JPA的工作方式与此相同。如果您想在对象中有一个标志告诉您它是父对象或子对象,请为它创建一个基本字段,允许您根据需要对其进行更改。但是我会为您创建最通用的根对象来处理这个“继承”,而不是依赖java继承谢谢您的回答。这个解决方案面临的一个问题是
em.remove(c)还通过级联持久化删除OneToMany相关对象。你知道解决这个问题的方法吗(除了删除cascade persist),因为我需要新的Parent-Object.Null上的OneToMany对象。您需要在删除之前清除所有引用,然后将这些引用添加到新实例中。不幸的是,这包括修复双向引用,并且由于需要额外的语句,这不是最有效的方法。如果您不使用共享缓存,您可能可以跳过修复远程引用以指向新实例,但将来会限制应用程序。