【问题标题】:OpenJPA CascadeType.DELETE causes Foreign Key constraint violationOpenJPA CascadeType.DELETE 导致外键约束违反
【发布时间】:2012-05-28 20:30:34
【问题描述】:

我在带有 Oracle 的 WebLogic 10.0.x 上使用 OpenJPA (JPA 1.0)。我已经定义了一个 OneToMany 关系如下:

@Entity
public class Compound implements Serializable {
    ...
    @OneToMany(mappedBy="compound", fetch=FetchType.LAZY, cascade=CascadeType.ALL)
    private List<Submission> submissions = new ArrayList<Submission>();
    ...
}

@Entity
public class Submission implements Serializable {
    ...
    @ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.REFRESH)
    @JoinColumn(name="compoundId")
    private Compound compound;
    ...
}

当我删除一个复合实体时,所有子提交实体也应该被删除。这作为一般规则起作用,除了我在这些表上设置了外键约束:

ALTER TABLE SUBMISSION
ADD CONSTRAINT FK_SUBMISSION_COMPOUND
    FOREIGN KEY (COMPOUNDID)
    REFERENCES COMPOUND(COMPOUNDID);

现在,当我尝试删除 Compound 实体时,遇到以下异常:

ORA-02292: integrity constraint (HELC.FK_SUBMISSION_COMPOUND) violated - child record found {prepstmnt 3740 DELETE FROM Compound WHERE compoundId = ? [params=(long) 10384]} [code=2292, state=23000]"

上述异常意味着 Open JPA 在将删除级联到子实体之前尝试删除父级。我通过 Google 阅读了几篇关于此异常的文章,可追溯到 2006 年。但是,最近的文章表明此错误已得到修复?

http://mail-archives.apache.org/mod_mbox/openjpa-dev/200609.mbox/%3C14156901.1158019042738.JavaMail.jira@brutus%3E

https://issues.apache.org/jira/browse/OPENJPA-235

谁能建议为什么这不起作用以及我能做些什么?我不愿意手动删除子实体,尤其是因为这是我的架构中不太复杂的关系之一,我为此使用的任何解决方案都需要在其他地方应用。

谢谢 周杰伦

【问题讨论】:

  • 您在 OpenJPA 方面有多少经验?是不是你 Submission 中的 CascadeType 有误?
  • OpenJPA?不多。我不知道 Submission 类中是否需要级联定义?这是一个依赖实体,因此如果父(复合)实体被删除,则应将其删除,但删除提交不应删除父实体。据我所知,我的代码是正确的。
  • 一件事 - 如上所述,这是 Weblogic 10.0.x。我怀疑我们使用的是捆绑版本的 OpenJPA / Kodo,它可能已经很老了......
  • 我认为这已经足够老了,您可能没有修复该错误。更新了我的答案。

标签: foreign-keys openjpa cascading-deletes


【解决方案1】:

当我删除一个复合实体时,所有子提交实体都应该 也被删除。这作为一般规则起作用,除了我有一个 这些表的外键约束设置:

如果您可以更改外键约束,那么就数据库而言应该可以解决问题。我不确定 OpenJPA 在这里的表现如何。

ALTER TABLE SUBMISSION
ADD CONSTRAINT FK_SUBMISSION_COMPOUND
    FOREIGN KEY (COMPOUNDID)
    REFERENCES COMPOUND(COMPOUNDID)
    ON DELETE CASCADE;

一件事 - 如上所述,这是 Weblogic 10.0.x。我怀疑我们 正在使用 OpenJPA / Kodo 的捆绑版本,这可能是 很老...

我自己的感觉是你提到的错误应该已经被这个版本修复了,但它也是 a) 时间足够接近以至于它可能没有被修复,并且 b) 可能是一个足够大的问题,我认为你应该花一些时间验证版本并修复。 (实际上,我刚刚注意到OpenJPA 1.0 was released on Aug 2007。这比我想象的要早得多,这使得您更有可能没有修复错误。)

如果您无法修改数据库(因为它是一个遗留系统,显然不打算让客户端依赖级联删除),并且如果您的版本中未修复错误,您将不得不管理SQL 语句的顺序自己。

手动管理 SQL 语句的负担——这是 OpenJPA 应该为你做的事情之一——可能足以让管理人员升级 OpenJPA 或更新外部数据库中的关键约束。

我真的希望你得到比这个更好的答案。

【讨论】:

  • 嗨猫叫。实际上我已经试过了。起初它似乎可以工作,但后来我开始从 JPA 收到错误消息,说子实体已在事务上下文之外进行了修改(我放错了确切的错误消息)。另外,我有点不愿意在数据库上添加删除级联。
  • 那个约束是由 OpenJPA 生成的吗?
  • 不,这是一个遗留数据库,我正在为它创建一个前端。这也是我不愿意添加 on delete 级联子句的原因之一,除非绝对必要。
  • 再次感谢您的回复 Catcall。我想你是对的。 modules目录下的版本分别是org.apache.openjpa_1.0.0.jar, com.bea.core.kodo_4.1.3.1.jar, com.bea.core.kodo.integration_1.0.1.0.jar, com.bea。 core.kodo.integration.tools_1.0.1.0.jar。它们听起来不是特别新:(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多