2

我的问题与更改保留其 ID 的实体的类型非常相似,但我使用的是 InheritanceType.JOINED 而不是 Table_per_class。

这意味着我不更改任何表,只是创建一个新的子类,其 id 与超类相同。

总而言之,我有一个 Person 类和一个 Doctor,它扩展了 Person 并具有相同的 id。我需要从数据库中检索一个 Person 并将其设置为 Doctor,保留 Person 实体中的所有数据,但为 Doctor 创建一些额外的数据。

尝试合并医生会生成一个新 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());
        }
    }
   }
4

1 回答 1

5

就像您链接到的问题一样,答案是“您不能使用 Hibernate API 做到这一点”。

原因实际上很清楚——Hibernate 旨在使持久性尽可能透明,因此,不能让你用持久性对象做一些普通 Java 对象无法做到的事情。一旦你创建了一个Person(在纯 java 中)的实例,它总是一个Person. 它永远不会是Doctor. 您可以做的最好的事情是创建一个Doctor实例并将Person's 属性复制到它。

然而,与普通的 java 不同,使用 Hibernate 你可以作弊并实现你想要的:-) 但它必须通过本机 SQL 来完成。在您的方法中,您需要:

  1. 从会话中驱逐Person实例(如果适用,还有二级缓存)
  2. 将具有匹配 ID(取自Person实例)的行插入Doctors表中。这是必须作为本机 sql 完成的部分,但您可以将其定义为命名查询并将上述 id 设置为参数。请注意,如果对Doctor属性有任何限制,您需要确保插入的值满足这些限制。
  3. 重新加载Person实例 - 现在将加载为Doctor.
于 2009-08-30T18:00:06.910 回答