删除子项时,JPA关系不会更新

时间:2011-04-26 15:33:03

标签: jpa-2.0 eclipselink cascading-deletes

鉴于以下情况:

@Entity
public class A {
  @OneToMany(mappedBy = "a", cascade = CascadeType.ALL)
  private List<B> bList;
}

@Entity
public class B {
  @ManyToOne()
  @JoinColumn(name = "a_id", referencedColumnName = "id")
  private A a;

  @ManyToOne()
  @JoinColumn(name = "c_id", referencedColumnName = "id")
  private C c;
}

@Entity
public class C {
  @OneToMany(mappedBy="c", cascade=CascadeType.ALL, orphanRemoval=true)
  @CascadeOnDelete // eclipselink specific optimization annotation
  private List<B> bList;
}

换句话说:对象A和对象C都包含许多B对象。

当我删除C对象时(从技术上讲,我正在更新包含多个C对象并使用orphanremoval的对象),我希望删除所有引用的B对象,它们按预期使用当前注释。但是,实体管理器似乎并不理解位于其缓存中的对象A现在已经丢失了一些孩子。如果我有一个A的实例,我当然必须手动更新它的bList,或者做一个新的查询来更新它,但即使是新获取的A对象仍然过时。重申:

  • 删除C对象。
  • 使用orphanRemoval将删除级联到B对象。
  • 实体管理器中缓存的对象中的bList 未更新
  • 手动清除实体管理器缓存使其可以检索正确更新的对象。

如何解决这个问题?我希望实体管理器能够自动更新其持久化上下文,或者在@JoinColumn上提供级联注释,但在这里似乎都不是这样。

编辑:似乎问题在于对象C的bList在对象A的bList更新时没有得到更新(因此无法级联更改)。我不知道为什么会这样..仍然注意到我在谈论持久性上下文而不是实例化的对象。

1 个答案:

答案 0 :(得分:6)

JPA不为您做关系维护,应用程序必须维护它们。这意味着当您删除实体时,应用程序负责清理对该实体的任何引用。很明显,当它是外键关系时,如果没有完成,数据库约束通常会导致异常。在后向引用的情况下,虽然关系没有严格的数据库约束,但用户通常会错误地认为JPA会处理它 - 使缓存损坏。

处理它的方法是删除对C和B实体的任何引用。在您的对象模型中,这意味着修复A的bList以删除Bs。我已经看到这通过实体删除事件或应用程序代码处理。由于在这种情况下,A没有外键,因此在删除发生后(即刷新或提交后),您也可以从数据库中刷新受影响的A实体。

相关问题