JPA:何时选择多值关联与元素集合映射

2022-09-01 06:15:45

我想更好地了解两者之间的区别

(1)传统的多值关系/关联

   @Entity -> @OneToMany -> @Entity

(2) 可嵌入(和基本)类型的 JPA2 集合

  @Entity -> @ElementCollection -> @Embeddable

我看到了语法上的差异,但想知道是否也有性能影响。在引擎盖下,数据库实现看起来非常相似。

直观地说,我通常会将 用于构图方案。但即使这样感觉也非常相似。@ElementCollectionCascadeType=DELETE

我在这里错过了本质吗?出于某些目的,一个是否比另一个更有效?

谢谢你,J。


答案 1

直观地说,我通常会将@ElementCollection用于构图方案。但即使这样,感觉也非常相似,就像CascadeType=DELETE一样。

它们是相似的,但有一些细微的差异。Java Persistence wikibook中的ElementCollection页面很好地总结了它:

Emded Collections

映射可用于定义对象集合。这不是对象的典型用法,因为对象不是嵌入在源对象的表中,而是存储在单独的集合表中。这类似于 a,只是目标对象是 而不是 。这允许轻松定义简单对象的集合,而无需简单对象定义映射或反向映射。 还可以重写其集合的映射或表,因此可以让多个实体引用同一类,但让每个实体将其依赖对象存储在单独的表中。ElementCollectionEmbeddableEmbeddableOneToManyEmbeddableEntityIdManyToOneElementCollectionEmbeddable

使用 a 而不是 a 的限制是,无法独立于其父对象查询、持久化和合并目标对象。它们是严格私有的(依赖的)对象,与映射相同。它们在 上没有选项,目标对象始终与其父对象一起持久化、合并、删除。 仍然可以使用提取类型,并默认为与其他集合映射相同。ElementCollectionOneToManyEmbeddedcascadeElementCollectionElementCollectionLAZY

另请参见


答案 2

JPA规范明确

嵌入对象不能独立于其父对象进行查询、持久化和合并。它们是严格私有的(依赖的)对象

应谨慎使用因为其生存期受所属实体实例的生存期限制。因此,如果您持久化/合并/删除您拥有的实体实例,则其所有可嵌入实例都将被持久化/合并/删除

假设你做了类似的事情

/**
  * Let's suppose owning contains SIX embeddables instances
  */
Owning owning = manager.find(Owining.class, owningId);

因此,您只需在视图图层上修改您的所属实体并提交更改。通过使用检索您的所属实体

/**
  * Usually your web framework Takes care of binding your submitted data
  */
Owning owning = new Owning();
owning.setProperty(request.getParameter("property"));

然后,您可以合并提交的数据,并且您认为您的嵌入式实例尚未存储在数据库中。好吧,让我们看看

如上所示,您(或您的Web框架)刚刚检索了拥有属性,???所以你的owning.getElementList()是空的。因为owning.getElementList()是空的,所以JPA将删除其所有可嵌入的实例。请记住这一点。

通常,可嵌入类与其所属实体以外的其他类没有关系。当使用一组可嵌入对象时,JPA总是在保存/更新之前选择,因为它需要使用其等于方法逐个比较。因此,在使用 Set 集合时,需要一个一致的 equals 实现

在这里,您可以在Hibernate中看到它的对应物。


推荐