EclipseLink:执行更新的级联删除问题

时间:2012-04-03 02:57:04

标签: java jpa eclipselink cascade

Oracle使用EclipseLink:

我在父(工作流)和子(阶段)之间有一对多的关系。在数据库中,我有一个删除约束,以便在工作流删除阶段删除。这可以从sqlplus中正常工作。

class Workflow {
    @Override
    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "workflow",      targetEntity = Stage.class)
    @JoinColumn(name = "WORKFLOW_ID")
    public Set<Stage> getStages() {
        return m_stages;
    }
}

class Stage {
    @Override
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, optional = false, targetEntity = Workflow.class)
    @JoinColumn(name = "WORKFLOW_ID", nullable = false)
    public Workflow getWorkflow() {
        return m_workflow;
    }
}

当我在@Transactional(propagation = Propagation.REQUIRED)方法中按名称加载工作流,然后em.remove(工作流)该对象时,

我得到例外,例如

Error Code: 1407
Call: UPDATE STAGES SET WORKFLOW_ID = ?, FAILURE_STAGE_ID = ?, SUCCESS_STAGE_ID = ? WHERE (STAGE_ID = ?)
bind => [4 parameters bound]

Caused by: java.sql.SQLException: ORA-01407: cannot update    ("DB"."STAGES"."WORKFLOW_ID") to NULL

因为我已将stages.workflow_id列定义为不可为空。

为什么eclipselink尝试使用null工作流ID更新阶段表,而不是仅仅删除阶段行本身?

我该如何解决?

2 个答案:

答案 0 :(得分:1)

当您使用mappedBy时,不应该在WorkFlow上使用JoinColumn,这很可能是原因。通常不应在OneToMany上使用JoinColumn(仅在JPA 2.0中允许),它仅适用于单向OneToManys。

否则包括事务的完整类和SQL跟踪。看起来它遇到了双向约束,并试图通过浅删除来解决它。你们之间有其他关系吗?

如果您在数据库中使用删除级联,则可以使用@CascadeOnDelete标记OneToMany关系以避免删除语句。

请参阅, http://wiki.eclipse.org/EclipseLink/Examples/JPA/DeleteCascade

答案 1 :(得分:0)

您删除工作流,注释属性mappedBy意味着阶段拥有其工作流,因此JPA实现更新阶段以使它们符合您映射theese实体的方式。

我想你要做的是删除工作流上的mappedBy。

更改阶段中的映射 像这样:

class Stage {
    @Override
    @ManyToOne(mappedBy="stages") // supposed to be the name (in Workflow) of the persisted property here, I'm not used to annotate on the getter
    // no JoinColumn - WorkFlow has already defined the relationship
    public Workflow getWorkflow() {
        return m_workflow;
    }
}

对于旧阶段(除了它不起作用的事实),您将删除工作流,因此如果删除了单个阶段,则删除该工作流中的所有其他阶段。 不要以为那是实际意图。