可嵌入和 ElementCollection 嵌套

Posted

技术标签:

【中文标题】可嵌入和 ElementCollection 嵌套【英文标题】:Embeddable and ElementCollection nesting 【发布时间】:2014-03-02 10:24:16 【问题描述】:

我有一个相当典型的场景,其中有一个主要的@Entity,他里面的所有东西都是可嵌入的(所以里面的所有东西没有父级就没有意义)。现在 JPA 2.0 阻止我将 @ElementCollection 嵌套在另一个 @ElementCollection 中定义的 @Embeddable 中:

JSR-317 2.6 可嵌入类和基本类型的集合 包含在元素集合中的可嵌入类(包括另一个可嵌入类中的可嵌入类)不得包含元素集合,也不得包含与多对一或一对一以外的实体的关系关系

现在的问题是:为什么会这样?一个简单的例子:

@Entity
public class Tournament 
    @Id
    Long id;

    @ElementCollection
    @CollectionTable
    private List<Edition>;


@Embeddable
public class Edition 

    @ElementCollection
    @CollectionTable
    private List<Round>


@Embeddable
public class Round 

    blabla;

这有什么问题?这只是一个示例,您可以将 Round 和 Edition 定义为 Entity 并解决问题,但在我的情况下,出于多种原因,我需要强制执行非常嵌套的东西没有他的父级就没有意义。

为什么 JPA 2.0 必须阻止我这样做?

【问题讨论】:

【参考方案1】:

您的情况违反了您粘贴的规范元素:

Edition 本身是@Embeddable,并且包含 Round 的元素集合,因此:

包含在元素集合 (Tournament.editions) 中的可嵌入类 (Edition) 不得包含元素集合 (Edition.rounds)。

至于为什么你不能这样做 - 如果你查看来自 http://en.wikibooks.org/wiki/Java_Persistence/ElementCollection 的示例,那么你会看到子(版本)将仅通过 FK 映射回所有者(Tournament.id)没有自己的 ID 列 - 因为作为 Weak 实体,它没有自己的 ID,仅通过引用锦标赛的 ID 来定义。

Take the Round,如果它也是一个弱实体,那么它应该由对版本的 FK 引用来定义 - 但我们已经说过它没有自己的 ID,所以你不能在没有 ID 的情况下将它映射到数据库中向版本添加一个 ID - 此时它本身就是一个实体,而不仅仅是@Embeddable。

查看下面评论中的 Wikipedia 示例 - http://en.wikipedia.org/wiki/Weak_entity - 弱实体的示例有 OrderNumber、CustomerNumber 等 - 只有嵌入另一个对象时才有意义。

您仍然可以拥有具有父映射(即版本中的锦标赛引用)和/或双向引用的实体。您可以通过 @ManyToOne 注释上的 nullable=false 属性强制在 Edition 上定义父级,从而强制执行模型的要求。

【讨论】:

正如我在问题中所写,模型需要它:如果没有锦标赛,就不可能加载版本,如果你没有锦标赛,版本就不能存在. Weak Entity 的概念在 ER 图中众所周知,但在 JPA 中似乎没有很好地实现。我只是想了解为什么在 JPA 中不能有更多嵌套的可嵌入元素集合(可能存在实现问题?),这是描述现实世界中事物的常用方式。 感谢您的详细解答。最后我意识到 Embeddable 并不完全符合弱实体的概念。弱实体应该有一个由父实体的外键+他自己的id组成的复合主键,而Embeddable对象则不是这样。所以我认为你给出的最后一个选项是最合理的,尽管我认为有更直接的方法来映射一个弱实体,但我错了。

以上是关于可嵌入和 ElementCollection 嵌套的主要内容,如果未能解决你的问题,请参考以下文章

@ElementCollection 的 JPA 延迟加载

是否可以通过 ElementCollection 查询 JPA 实体,其中 ElementCollection 包含给定元素集中的所有元素?

Hibernate - @ElementCollection - 奇怪的删除/插入行为

Spring boot @ElementCollection:“字段列表”中的未知列“user_roles”

如何在休眠中为@ElementCollection 设置表名

JPA @ElementCollection 我该如何查询?