Reputation: 28568
Oracle using EclipseLink:
I have a one to many relationship between a parent (workflow) and children (stage). In the database i have a delete constraint such that deletes on workflow delete stage. This works fine from 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;
}
}
when i load the workflow by name inside a @Transactional(propagation = Propagation.REQUIRED) method and then em.remove(workflow) that object,
I get exceptions, such as
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
because I have defined the stages.workflow_id column to be not nullable.
Why is eclipselink trying to update the stages table with null workflow ids, rather than just deleting the stage row itself?
How do i fix that?
Upvotes: 5
Views: 3475
Reputation: 18379
You should not have the JoinColumn on the WorkFlow as you are using a mappedBy, that is most likely the cause. A JoinColumn should normally not be used on a OneToMany (was only allowed in JPA 2.0), it is only for unidirectional OneToManys.
Otherwise include the full classes and SQL trace of the transaction. It looks like it is encountering a bidirectional constraint, and trying to resolve it through a shallow delete. Do you have other relationships between the two?
If you are using delete cascading in the database you can mark the OneToMany relationship with @CascadeOnDelete to avoid the delete statement.
See, http://wiki.eclipse.org/EclipseLink/Examples/JPA/DeleteCascade
Upvotes: 1
Reputation: 3059
You remove the workflow, the annotation property mappedBy means that stages owns their workflow, so JPA-implementation updates the stages to make them conform to the way you mapped theese entities.
My guess at what you want to do is to remove the mappedBy on Workflow.
Change the mappings in Stages like this:
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;
}
}
With the old stages (besides the fact it didn't work) you would delete a Workflow and hence delete all other stages in that workflow if you deleted a single stages. Don't think that was the actual intention.
Upvotes: 0