JPA继承 - 更改实体类型

时间:2013-11-20 14:36:07

标签: jpa inheritance

我有两个班级

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="PERSONTYPE")
@DiscriminatorValue(value="PERSON")
public class Parent {
  .......
}


@Entity
@DiscriminatorValue(value="CHILD")
public class Child extends Parent{
  .......
}

我的情景:

  1. 创建一个人 - 然后是PERSONTYPE ='PERSON'

  2. 进入“人物”页面并通过选中“儿童”复选框将其更新为“儿童”,然后在保存之后必须将人员保存为“儿童”类型。

  3. 那么如何将实体类型从“PERSON”更改为“CHILD”?

3 个答案:

答案 0 :(得分:0)

以下是几种可能性:

似乎显而易见的事情是在Parent对象上设置isIsChild(true)并提交它,但是我不确定JPA将如何对此做出反应,因为你现在提交了一个Parent并且结果是一个Child 。不确定这是可能的。绝对值得一试。

另一种选择是编写JPA更新语句(绕过Child和Parent对象)来更新数据库中的is_child列。然后,当您随后查询此记录时,您将获得一个Child而不是Parent。

最后,您可以使用父对象的所有值创建子对象,然后删除父对象,并创建子对象。这将起作用,但是除了删除/创建所需的额外处理,而不是简单的更新,子项的ID可能会更改(如果您使用自动生成的ID,它将更改)。 IMO,这不是一个好的解决方案,但它会起作用。

答案 1 :(得分:0)

我假设您拥有Child Object的唯一属性,这就是您想要使用继承的原因,正如@ZB Ziet所评论的那样,您应该只使用子标志

解决方案1 ​​

我发现你正在使用单表继承策略,因此你必须修改descriminator字段manulay(通过使用SQL查询)并在子表上设置appropirate字段。

UPDATE Parent SET PERSONTYPE='CHILD' WHERE id = 1

实际上你使用像这样的本地查询

enityManager.createNativeQuery(“UPDATE PERSON SET PERSONTYPE = ?, ”
“ VERSION = VERSION + 1 WHERE ID = ?”)
.setParameter(1, 'CHILD')
.setParameter(2,personID)
.executeUpdate();

然后您可以使用entitymanager获取子项并设置属性

entityManager.find(Child.class,1).childProp=xxxx

**解决方案2 **

IMO,这里最好的办法是使用加入表策略

而不是使用单表策略

在连接表策略中,新表为每个具有id作为父实体的外键的子进程创建整数。所以更改id也将设置其父对象

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Person { 
...

如果您可以创建新的子设置id与父设备相同并保存,那将会很酷。 Child c = new Child(); c.setId(parent.getId()); entityManager.merge(c)。但是hibernate试图重新创建一个父对象,导致id confilict。

因此解决方案是编写本机查询     em.createNativeQuery("INSERT into child (id) VALUES (1)").executeUpdate(); //1 being the parent id

more reference on inheritance

答案 2 :(得分:0)

使用EntityMaster

想法是创建一个仅用于更改区分符的实体。

至少该实体需要具有ID和鉴别符。

@Entity
public class ParentMaster {

 public static final PERSON="PERSON";
 public static final CHILD="CHILD";

 private Long id;
 private String persontype;

 //getter setter
}

现在通过id和pm.setPersontype(ParentMaster.CHILD);加载ParentMaster。