我很难提出这个问题。随意询问是否需要澄清。
情况:我有一个使用Hibernate的Spring应用程序将不同的Entity-Class持久化在数据库中。为简化起见,将这些类称为E1, E2, .., E20
。所有这些类都基于相同的抽象@MappedSuperclass
,但是没有真正的继承(在数据库方面)。
现在,我想添加新的实体类(En1, En2, ...
)并与一些现有实体建立双向关系。假设En1
与E1,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)
中删除newAttribute
和E1,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 <-> E3
和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
)一次只能与一个其他实体(例如:E1
或E3
)建立关联。