嵌入式类和双向关系

时间:2017-10-20 14:30:31

标签: java spring hibernate

这个问题对我来说很难制定。如果需要澄清,请随时询问。

情况:我有一个使用Hibernate的Spring-Application在数据库中保存不同的Entity-Classes。为简化调用这些类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中有一个attribut,并且必须在每个现有实体中复制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类,但这不会与其他新的实体类一起扩展。假设以下情况,新实体En2,..,En4应与以下实体相关:

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

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

如何在不重复代码的情况下解决此问题的任何建议?

2 个答案:

答案 0 :(得分:1)

我认为为了更好地解决您的模型,您可以使用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用于hibernate继承:

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

    @ManyToOne
    private E e;

    // ...

}

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

例如,如果您要保存En2 <-> E3&amp; En3 <->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)有关联一时间。

答案 1 :(得分:0)

您可能希望为E1,E2,...,E20定义泛型类型,这样您只需要使用单个E类型集合定义En类。 E的每个实现都可以不同,但​​您不需要更改En类,因为它只是包含E类型的集合。

Here's a link to a guide that may help.