首页 > 解决方案 > 与他人共享 OneToMany 的最佳做法是什么?

问题描述

假设我有一张看起来像这样的桌子。

K VARCHAR PK
V VARCHAR

它只是一个存储键和值条目的表。

现在,我希望它通常用于其他实体。

实体 A 具有多个属性,而实体 B 可以具有多个属性。

@Entity
class Property {

    String key;
    String value;
}

Property将实体共享给其他实体的最佳做法是什么?

@Entity
class Some {

    @OneToMany
    private List<...Property> properties;
}

@Entity
class SomeOther {

    @OneToMany
    private List<...Property> properties;
}

我打算使用继承。

@Entity
@Inheritance
class Property {
}

我知道我可以扩展它。

@Entity
@DiscriminatorValue("SomeOther")
class SomeProperty extends Property {
}

@Entity
@DiscriminatorValue("SomeOther")
class SomeOtherProperty extends Property {
}

现在我的桌子应该是什么样子?

我应该创建SOME_PROPERTY表吗?

或者我应该添加SOME_IDPROPERTY表中?

标签: jpaentity-relationship

解决方案


就个人而言,我会尽量保持简单。

当前映射,即:

@Entity
class Some {

    @OneToMany
    private List<Property> properties;
}

创建一个连接表,将 和 中的行链接SOME起来PROPERTY。你会得到几乎相同的InheritanceType.JOINED

如果您稍微修改映射:

@Entity
class Some {

    @OneToMany
    @JoinColumn
    private List<Property> properties;
}

你最终会得到一个PROPERTY指向的外键SOME(并且重用这个映射SomeOther会导致另一个外键)。你会得到几乎相同的InheritanceType.SINGLE_TABLE

在这里使用继承只会使事情复杂化。我会选择上述选项之一,或者使用更简单的映射:

@Entity
public class Some {

    @ElementCollection
    @MapKeyColumn(name = "K")
    @Column(name = "V")
    @CollectionTable(name = "PROPERTY", joinColumns = @JoinColumn(name = "some_id"))
    private Map<String, String> properties;
}

上面将属性表示为 a Map<String, String>,实际上它们就是这样。唯一的缺点是,当您重用此映射时(仅更改连接列名称,例如some_other_id),您的 JPA 提供者可能难以生成模式。当然,您可以决定将不同实体的属性分开,在这种情况下,您可以更改集合表名称(然后您将获得 的等价物Inheritance.TABLE_PER_CLASS)。

顺便说一句,我认为K作为主键没有意义,假设键将针对Some. 如果您决定使用其中一种解决方案@OneToMany,我建议您向实体 添加一个代理键(一个@Id @GeneratedValue Long id字段) 。Property


推荐阅读