jpa如何创建与父实体具有相同id的新实体(JOINED继承)

时间:2009-08-30 14:46:49

标签: hibernate inheritance jpa joined-subclass

我的问题与Changing the type of an entity preserving its ID非常相似,但我使用的是InheritanceType.JOINED而不是Table_per_class。

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

总结一下,我有一个Person类和一个Doctor,它扩展了Person并且具有相同的id。 我需要从数据库中检索一个Person并使其成为Doctor,保留Person实体中的所有数据,但为Doctor 1创建一些额外的数据。

尝试合并医生会产生一个新的身份证,这对我无效。

这是我在第一时间尝试的内容

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

1 个答案:

答案 0 :(得分:4)

就像您链接到的问题一样,答案是“您无法使用Hibernate API执行此操作”。

原因实际上非常清楚 - Hibernate旨在使持久性尽可能透明,因此,不能允许您使用普通Java无法执行的持久对象。一旦创建了Person的实例(在普通的java中),它始终是Person。它永远不会是Doctor。您可以做的最好的事情是创建一个Doctor实例并将Person的属性复制到其中。

与普通的java不同,使用Hibernate,你可以欺骗并实现你想要的东西:-)但它必须通过原生SQL来完成。在您的方法中,您需要:

  1. 从会话中撤消Person实例(如果适用,则为二级缓存)
  2. 将具有匹配ID的行(从Person实例中取出)插入Doctors表。这是必须以本机sql完成的部分,但您可以将其定义为命名查询并将上面的id设置为参数。请注意,如果对Doctor属性有任何限制,则需要确保插入的值满足它们。
  3. 重新加载Person个实例 - 现在将加载为Doctor