JPA : What is the behaviour of merge with lazy initialized collection?

标签 jpa jpa-2.0

以下是导致问题的序列:

  1. 我的数据库中有一条球队记录和 3 名球员记录。团队实体有一个使用 FetchType.LAZY、CascadeType.ALL 的列表
  2. 点击了 WebUI 上的搜索按钮
  3. 调用服务器端使用 JPA 查询的查询,查找所有团队记录,在本例中,仅查询返回团队实体的 1 条记录(具有玩家实体列表的代理)
  4. 将此 teamEntity 映射到 DTO,并将此 DTO 返回到 WebUI,跳过玩家实体列表的映射
  5. Webui 以 html 形式呈现 DTO,准备接收用户的修改
  6. 用户修改团队的属性,例如团队的成立日期
  7. 单击 WebUI 上的“保存”按钮
  8. 将 DTO 转换为团队实体,用于更新现有团队记录
  9. 但是在这种情况下,如果我使用 em.merge(teamEntity),球队记录将被更新,但是球员列表会发生什么?因为当从 DTO 转换为团队实体时,团队实体有一个空的玩家实体列表。合并后,我注意到 teamEntity 的详细信息大小为 0。但刷新该实体 em.refresh(teamEntity) 后,它将返回详细大小的 3。

我很困惑:

  1. 为什么合并后大小为0?就像不再代表记录一样
  2. 在进行测试之前,我认为细节将被删除,因为我将 teamEntity 与空细节合并。

请赐教:)

谢谢!

最佳答案

JPA 规范说:

The semantics of the merge operation applied to an entity X are as follows:

  • If X is a detached entity, the state of X is copied onto a pre-existing managed entity instance X' of the same identity or a new managed copy X' of X is created.

  • If X is a new entity instance, a new managed entity instance X' is created and the state of X is copied into the new managed entity instance X'.

  • If X is a removed entity instance, an IllegalArgumentException will be thrown by the merge operation (or the transaction commit will fail).

  • If X is a managed entity, it is ignored by the merge operation, however, the merge operation is cascaded to entities referenced by relationships from X if these relationships have been annotated with the cascade element value cascade=MERGE or cascade=ALL annotation.

  • For all entities Y referenced by relationships from X having the cascade element value cascade=MERGE or cascade=ALL, Y is merged recursively as Y'. For all such Y referenced by X, X' is set to reference Y'. (Note that if X is managed then X is the same object as X'.)

  • If X is an entity merged to X', with a reference to another entity Y, where cascade=MERGE or cascade=ALL is not specified, then navigation of the same association from X' yields a reference to a managed object Y' with the same persistent identity as Y.

如您所见,这里没有魔法。分离实例的状态被复制到新创建的托管实例中。由于您的分离实例有一个空列表,托管实例也会有它。

进一步的行为取决于关系的所有权,因为数据库中的表示反射(reflect)了关系的拥有方:

  • 如果Team是拥有方,TeamPlayer之间的关系将在刷新期间被破坏(但是Player code> 本身将继续存在,除非您的关系中有 orphanRemoval = true)。
  • 否则,Team 中的空列表不会影响数据库。

如果在刷新上下文之前刷新TeamTeam的所有属性都会被数据库中的值重写,因此Player列表s 已恢复(因为空玩家列表尚未刷新)。

如果在调用 refresh() 之前调用 flush(),并且 Team 是拥有方,则列表将为空,因为销毁关系在 flush() 期间传播到数据库。

关于JPA : What is the behaviour of merge with lazy initialized collection?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5244238/

相关文章:

mysql - EclipseLink JPA 辅助服务器

java - @GenericGenerator(name = "generator", strategy = "foreign") 到标准 JPA 2

spring - 在 JPA/hibernate 和 spring 中使用 joda time

java - 为什么使用 JPA 而不是使用 JDBC 编写 SQL 查询?

java - 没有名为 X 的 EntityManager 的持久性提供程序 - JPA

java - 当 "parent"表具有复合 PK 时,如何在 JPA 中建模一对一关系?

java - EclipseLink JPA2 Criteria 查询准备语句

jpa-2.0 - JPA - 只有第一次提交失败,但应该全部失败

java - 是否有任何与 JPAv2 兼容的供应商不可知持久性 api 公开可用

java - Oracle 通过 JPA 排序,数字在前