1

想象一下简单的“树”JPA 实体:

public class TreeItem {
  @OneToMany(mappedBy = "parentItem")
  private List<TreeItem> childItems;
  @ManyToOne
  @JoinColumn(name = "parent_id"
  private TreeItem parentItem;
  @Column
  private String name;
}

现在,这些实体之一正在被加载、传递到 Web 层、更新并传递回 EJB 以进行保存操作。我注意到的是,在merge()操作过程中,在发出updatesql 命令之前加载整个树,无论该实体在树中驻留多深。为什么会这样?我看不出这种行为背后的任何原因,因为我没有设置级联选项。

更新: 是的,传回的实体是分离的,需要将其状态与数据库层同步,这就是我所理解的。但我不明白的是,为什么同步需要阅读整棵树,而不考虑关系的懒惰。

4

1 回答 1

0

以下是规范如何定义合并操作:

应用于实体 X 的合并操作的语义如下:

  • 如果 X 是分离实体,则 X 的状态被复制到具有相同身份的预先存在的受管实体实例 X' 上,或者创建 X 的新受管副本 X'。
  • 如果 X 是一个新的实体实例,则创建一个新的托管实体实例 X',并将 X 的状态复制到新的托管实体实例 X'。
  • 如果 X 是已移除的实体实例,则合并操作将抛出 IllegalArgumentException(或事务提交将失败)。
  • 如果 X 是一个托管实体,则合并操作将忽略它,但是,如果这些关系已使用级联元素值 cascade=MERGE 或 cascade=ALL 注释进行注释,则合并操作将级联到由来自 X 的关系引用的实体。
  • 对于由来自 X 的具有级联元素值 cascade=MERGE 或 cascade=ALL 的关系引用的所有实体 Y,Y 被递归地合并为 Y'。对于由 X 引用的所有此类 Y,X' 设置为引用 Y'。(请注意,如果 X 是托管的,则 X 是与 X' 相同的对象。)
  • 如果 X 是合并到 X' 的实体,并引用另一个实体 Y,其中未指定 cascade=MERGE 或 cascade=ALL,则从 X' 导航相同关联会产生对托管对象 Y' 的引用,其中与 Y 相同的持久身份。

持久性提供程序不得合并标记为 LAZY 且尚未获取的字段:合并时必须忽略此类字段。

实体使用的任何版本列必须在合并操作期间和/或在刷新或提交时由持久性运行时实现检查。在没有版本列的情况下,持久性提供程序运行时不会在合并操作期间进行额外的版本检查。

因此,除非您传递的分离对象将 parentItem 作为惰性引用或 null,否则需要从数据库中获取其状态以与分离实例同步。

于 2012-10-05T20:55:33.740 回答