我有两个班级
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="PERSONTYPE")
@DiscriminatorValue(value="PERSON")
public class Parent {
.......
}
@Entity
@DiscriminatorValue(value="CHILD")
public class Child extends Parent{
.......
}
我的情景:
创建一个人 - 然后是PERSONTYPE ='PERSON'
进入“人物”页面并通过选中“儿童”复选框将其更新为“儿童”,然后在保存之后必须将人员保存为“儿童”类型。
那么如何将实体类型从“PERSON”更改为“CHILD”?
答案 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
答案 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。