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更新阶段表,而不是仅仅删除阶段行本身?
我该如何解决?
答案 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;
}
}
对于旧阶段(除了它不起作用的事实),您将删除工作流,因此如果删除了单个阶段,则删除该工作流中的所有其他阶段。 不要以为那是实际意图。