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

时间:2017-06-01 12:03:17

标签: jpa inheritance eclipselink

我知道similar questions,但他们在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;
}

现在我想将Child改为Parent,反之亦然,例如

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);

在这种情况下,我希望cdtype = parent一起保存并失去childProperty的值。

上面描述的内容不起作用,但我写下来表明我的意思。

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

1 个答案:

答案 0 :(得分:2)

如果要将对象从一种类型“更改”为另一种类型,则没有简单的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,但是不能保证因为管理二级缓存变得棘手。另请注意,需要更新与子项的所有关系以指向“新”父实例,否则缓存将被损坏。

我不太确定这一点,因为在这种情况下,Child已经是一个父实例。除了数据库中的任意标志之外,这种方法没有获得任何东西。如果您希望它可以随时更改,那么使用Java子类可能不适合您的应用程序。

相反,我建议使用具有可设置为保持子/父状态的字段的通用Person。但由于孩子可以同时成为父母..