我的问题与 Changing the type of an entity preserving its ID 非常相似,但我使用 InheritanceType.JOINED 而不是 Table_per_class。
这意味着我不更改任何表,只是创建一个新的子类,其 id 与父类(super class)相同。
总而言之,我有一个 Person 类和一个 Doctor,它扩展了 Person 并且具有相同的 id。 我需要从数据库中检索一个 Person 并将其设为 Doctor,保留 Person 实体中的所有数据,但为 Doctor 实体创建一些额外的数据。
尝试合并医生会生成一个新 ID,该 ID 对我无效。
这是我首先尝试过的
private Person getDoctor(Person person) {
// Person already a doctor ==> OK
if (person instanceof Doctor) {
return person;
}
// Transient Person ==> //Transient Doctor OK
if (person == null) {
return new Doctor();
}
// Creates a Doctor from the person (only setting id...),
// and merges it ==>
fails as the id changes.
Doctor doctor = new Doctor(person);
return personDAO.merge(doctor);
}
sorry guys,first time here.
Here´s the code above:
private Person getDoctor(Person person) {
//Person already a doctor ==> OK
if (person instanceof Doctor) {
return person;
}
//Transient Person ==> //Transient Doctor OK
if (person == null) {
return new Doctor();
}
//Creates a Doctor from the person (only setting id...), and merges it ==> fails as the id changes.
Doctor doctor = new Doctor(person);
return personDAO.merge(doctor);
}
@Inheritance(strategy = InheritanceType.JOINED)
@Entity
public class Person{
}
@Entity
public class Doctor extends Person{
public Doctor(Person person) {
if (person != null) {
this.setId(person.getId());
}
}
}
最佳答案
就像您链接到的问题一样,答案是“您无法使用 Hibernate API 执行此操作”。
原因实际上很清楚 - Hibernate 的目标是使持久性尽可能透明,因此,它不允许您使用持久对象做一些普通 Java 对象无法做的事情。一旦您创建了 Person
实例(用纯 java 编写),它始终是一个 Person
。它永远不会成为一名医生
。您能做的最好的事情就是创建一个 Doctor
实例并将 Person
的属性复制到其中。
然而,与普通的 java 不同,使用 Hibernate 你可以作弊并实现你想要的:-),但它必须通过 native SQL 来完成。在您的方法中,您需要:
- 从 session 中删除
Person
实例(以及二级缓存(如果适用)) - 将具有匹配 ID 的行(取自
Person
实例)插入到Doctors
表中。这是必须作为 native sql 完成的部分,但您可以将其定义为命名查询并将上面的 id 设置为参数。请注意,如果Doctor
属性有任何限制,您需要确保插入的值满足这些限制。 - 重新加载
Person
实例 - 现在将作为Doctor
加载。
关于hibernate - jpa如何创建与父实体具有相同id的新实体(联合继承),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1354037/