我很难提出这个问题。随意询问是否需要澄清。

情况:我有一个使用Hibernate的Spring应用程序将不同的Entity-Class持久化在数据库中。为简化起见,将这些类称为E1, E2, .., E20。所有这些类都基于相同的抽象@MappedSuperclass,但是没有真正的继承(在数据库方面)。

现在,我想添加新的实体类(En1, En2, ...)并与一些现有实体建立双向关系。假设En1E1,E2,E3存在关联,我的代码如下所示:

@Entity
public class E1 extends SuperClass {
  //other attributes

  @OneToMany(mappedBy = "e1")
  List<En1> newAttribut;

  public En1 doMagic(En1 entity) {
    //a long function which does somthing with the entity
  }

  //other attribute
}

//-----------------------------//
// The same code for E2 and E3 //
//-----------------------------//

@Entity
public class En1 {
  //other attributes

  @ManyToOne
  E1 e1;

  @ManyToOne
  E2 e2;

  @ManyToOne
  E3 e3;

  //other attributes
}


问题:此解决方案扩展性不好。对于每个关系,我都需要在类En1中提供一个属性,并且必须在每个现有实体中复制doMagic()方法。此外,在实践中,实体En1一次只能与一个其他实体建立联系。因此,三分之二的属性将是null

尝试过的解决方案:@Embeddable的使用解决了在E1,..,E3中重新实现相同代码的问题

public class EmbeddedEn1 implements Serializable {

  @OneToMany(mappedBy="parentEntity")
  private List<En1> newAttribut;

  public En1 doMagic(En1 entity) {
    //a long function which does somthing with the new entity
  }
}


但是"parentEntity"双向无法建立。

继承不起作用:当然,我可以使用像hasAttributEn1这样的类,该E1,E2,E3继承自该类,但这不能与其他新的Entity-Class一起扩展。假定存在以下情况,其中新实体En2,..,En4应与以下实体相关:


En2 <-> E1, E3
En3 <-> E2,E3
En4 <-> E1,E2


在这种情况下,将需要多个继承。

有什么建议可以解决此问题而不重复代码吗?

最佳答案

我认为为了更好地解决您的模型,可以使用hibernate inheritance

因此,对于实体En1,为E1,E2,E3...创建一个父类:

@Entity
// TABLE_PER_CLASS will create a table for each subclass with all attributes
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
//....
//Abstract entity, so you won't need to create a table for it
public abstract class E extends SuperClass {

   // shared attributes & methods
   @OneToMany(mappedBy = "e")
   private List<En> newAttribut;

   public En doMagic(En entity) {
       //a long function which does something with the new entity
   }
   //...


}


从您的doMagic(En1)中删除​​newAttributeE1,E2,E3,因为它们将从父类E继承它们


更新:

正如您在评论中(以及在您的问题中)所提到的,您需要将E类与一个以上的En类相关联。
为了简单起见,我还将对En使用休眠继承:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class En{

    @ManyToOne
    private E e;

    // ...

}


因此,每个En1, En2,..., Enx都将从此类继承。

例如,如果要保存En2 <-> E3En3 <->E3(此示例仅用于说明目的,并且不涉及其他方面,例如事务):

En en2 = new En2();
En en3 = new En3();
E e3 = new E3();
en2.setE(e3);
e3.getEn().add(en2);

en3.setE(e3);
e3.getEn().add(en3);
session.save(e3)
session.save(en2)
session.save(en3)


最后,您将满足您的约束条件:


doMagin()方法的一个副本,
En的子实体(例如:En1)一次只能与一个其他实体(例如:E1E3)建立关联。

10-05 20:01