了解EntityManager的合并操作的行为

时间:2012-10-05 11:54:28

标签: hibernate jpa jpa-2.0 ejb-3.0

想象一下简单的“树”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()操作期间,在发出update sql命令之前,整个树都被加载,无论该实体在树中有多深。为什么会这样?我无法看到这种行为背后的任何原因,因为我没有设置级联选项。

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

1 个答案:

答案 0 :(得分:0)

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

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

  • 如果X是分离的实体,则将X的状态复制到a 创建相同标识的预先存在的托管实体实例X'或创建X的新托管副本X'。
  • 如果X是新的实体实例,则新的管理实体实例X'是 创建并将X的状态复制到新的管理实体中 实例X'。
  • 如果X是已删除的实体实例,则将抛出IllegalArgumentException 合并操作(或事务提交将失败)。
  • 如果X是托管实体,则合并操作会忽略它, 但是,合并操作会级联到引用的实体 如果这些关系已被注释,则来自X的关系 cascade element value cascade = MERGE或cascade = ALL annotation。
  • 对于来自X的关系引用的所有实体Y具有 级联元素值级联= MERGE或级联= ALL,Y合并 递归地为Y'。对于所有由X引用的Y,X'设置为 参考Y'。 (注意,如果X被管理,那么X是与之相同的对象 X”)
  • 如果X是合并到X'的实体,则引用另一个实体Y, 其中cascade = MERGE或cascade = ALL未指定,然后导航 来自X'的相同关联产生对托管的引用 对象Y'与Y具有相同的持久性标识。

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

在合并操作期间和/或刷新或提交时,必须由持久性运行时实现检查实体使用的任何版本列。如果没有Version列,则在合并操作期间,持久性提供程序运行时不会执行其他版本检查。

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