我正在开发一个Java应用程序,它通过Hibernate将数据存储在数据库中。
此应用程序的一个功能是定义类型等模板以供重用。例如,类型具有属性,您可以创建类型的实例,该实例具有属性的值。
问题是,我不知道如何确保只分配属性定义的属性值。在我的解决方案中有一个导致问题的冗余,但我不知道如何删除它。
我目前的(并且有问题的)方法如下:
@Entity
class Type
{
@Id
@Generated
private Long id;
@OneToMany(mappedBy="type")
private List<Attribute> attributes;
//...
}
@Entity
class Attribute
{
@Id
@Generated
private Long id;
@ManyToOne
private Type type;
//...
}
@Entity
class Instance
{
@Id
@Generated
private Long id;
@ManyToOne
private Type type;
//...
}
@Entity
class AttributeValue
{
@Id
@Embedded
private ResourceAttributValueId id;
@Column(name="val")
private String value;
//...
}
@Embeddable
public class ResourceAttributValueId implements Serializable
{
@ManyToOne
private ResourceStateImpl resource;
@ManyToOne
private ResourceAttributeImpl attribute;
//...
}
在那里,类型的定义是多余的:可以通过AttributeValue-&gt; Attribute-&gt; Type和AttributeValue-&gt; Instance-&gt; Type
来访问类型另一个想法是使用type + attribute name作为属性的id,使用instance + attribute name作为属性值的id,但这并不能解决我的问题。
答案 0 :(得分:2)
正确建模“菱形”依赖关系的关键是使用识别关系:
(我冒昧地稍微重命名你的实体,我相信这是一个更加一致的命名方案。)
请注意我们如何从钻石顶部迁移 {/ 1}},从两侧向下,一直到底部,然后合并。因此,由于只有一个TYPE_ID
字段并且涉及两个FK,我们永远不会有属性类型的类型与实例类型不同的属性实例。
虽然这可以避免“不匹配”属性,但它仍然无法确保属性实例的存在(如果您支持“必需属性”的概念),最好在应用程序级别强制实施。从理论上讲,你可以在数据库级别使用循环延迟FK来强制执行它,但并非所有DBMS都支持它,我怀疑它会与ORM很好地配合。
不幸的是,我对Hibernate的经验不足以回答是否可以将其映射到那里以及如何映射。
另见: