I am working migrating project to a pure JPA annotation based mapping from an XML mapping and I am running into an issue when trying to delete (remove) and entity and its children. It works in with XML mapping and does not work with the annotation mapping.
The XML mapping looks like this:
<set name="evaluations" order-by="evalDate desc" table="Evaluation" lazy="true" inverse="true" cascade="delete">
<key column="requestId" />
<one-to-many class="org.stuff.model.Evaluation" />
</set>
The annotation mapping, as far as I can tell is this:
@OneToMany(orphanRemoval=true)
@JoinColumn(name = "requestId")
@OrderBy("evalDate DESC")
private Set<Evaluation> evaluations = new TreeSet<>();
This is a uni-directional relationship.
The JPA code to delete the entity is:
ServiceRequest sr = em.getReference(ServiceRequest.class, id);
em.remove(sr);
Where the above Evaluation
is a child object of ServiceRequest
. Hibernate 4.3.7 is the JPA Impl I am using, running on WildFly 8.2.
With Hibernate set to barf out its SQL, executing the remove with the annotation mapping in place Hibernate produces a query to look up the Entity reference and then when the remove
is called it produce an update trying to update the child record in Evaluation
FK back to ServiceRequest to be null:
Hibernate: update Evaluation set requestId=null where requestId=?
And that blows up because there is a not null
constraint on requestId
.
If I do the same operation using the XML mapping (see above snippet) it works just fine. All child entities are deleted along with the parent. and Hibernate only produces selects
and deletes
, if never tries to update anything.
This feels like I have the annotation mapping wrong, but I cannot figure where I went wrong. Please help.
You xml config actually says the relationship between your ServiceRequest and Set are bi-directional because inverse = "true".
But your JPA annotation is uni-directional. so this should work (edited after OP's comment)
@OneToMany(orphanRemoval=true,mappedBy="requestId")
@OrderBy("evalDate DESC")
private Set<Evaluation> evaluations = new TreeSet<>();
Here mappedBy="requestId"
tells Hibernate that this is owner side of the relationship. So it will issue statement to remove Evaluation.