类型,属性,实例和值之间的关系

我正在开发一个Java应用程序,它通过Hibernate将数据存储在数据库中。

该应用程序的一个特征是定义类型等模板以供重用。 例如,类型具有属性,您可以创建类型的实例,该实例具有属性的值。

问题是,我不知道如何确保只分配属性定义的属性值。 在我的解决方案中有一个导致问题的冗余,但我不知道如何删除它。

我当前(和有问题的)方法看起来像这样:

@Entity class Type { @Id @Generated private Long id; @OneToMany(mappedBy="type") private List 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-> Attribute-> Type和AttributeValue-> Instance-> Type来访问类型

另一个想法是使用type + attribute name作为属性的id,使用instance + attribute name作为属性值的id,但这并不能解决我的问题。

正确建模像这样的“菱形”依赖关系的关键是使用识别关系:

在此处输入图像描述

(我冒昧地稍微重命名你的实体,我相信这是一个更一致的命名方案。)

请注意我们如何从钻石顶部向下移动 TYPE_ID从两侧向下移动,然后合并到那里。 因此,由于只有一个ATTRIBUTE_INSTANCE.TYPE_ID字段并且两个FK都参与其中,我们永远不会有属性类型的类型与实例类型不同的属性实例。

虽然这样可以避免“不匹配”属性,但它仍然无法确保属性实例的存在 (如果您支持“必需属性”的概念),这在应用程序级别最佳实施。 从理论上讲,你可以在数据库级别使用循环延迟FK来强制执行它,但并非所有DBMS都支持它,我怀疑它会与ORM很好地协作。

不幸的是,我对Hibernate的经验不足以回答它是否可以映射到那里以及如何映射。

也可以看看:

  • 从多个候选键中选择
  • 如何在“钻石形”的关系系统中保持外键关系的一致性