MeB*_*Guy 5 java jpa cascade eclipselink
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;
}
}
Run Code Online (Sandbox Code Playgroud)
当我在@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
Run Code Online (Sandbox Code Playgroud)
因为我已将stages.workflow_id列定义为不可为空.
为什么eclipselink尝试使用null工作流ID更新阶段表,而不是仅删除阶段行本身?
我该如何解决这个问题?
您删除工作流,注释属性mappedBy 意味着阶段拥有其工作流,因此JPA 实现会更新阶段以使它们符合您映射这些实体的方式。
我猜你想要做的就是删除工作流上的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;
}
}
Run Code Online (Sandbox Code Playgroud)
对于旧阶段(除了它不起作用之外),您将删除工作流程,因此如果您删除了单个阶段,则删除该工作流程中的所有其他阶段。不要认为这才是真正的意图。