#StackBounty: #java #hibernate #jpa OneToMany relationship orphans are not removed from the DB

Bounty: 50

Originally this problem/bug posted on Hibernate’s JIRA: https://hibernate.atlassian.net/browse/HHH-12311

My log properties are set to:

logging.level.org.hibernate.SQL: TRACE
logging.level.org.hibernate.event.internal: TRACE
logging.level.org.hibernate.engine.spi.CollectionEntry: TRACE
logging.level.org.hibernate.engine.spi: TRACE
logging.level.org.hibernate.engine.internal: TRACE

I have two entities: Job and Step
Job has a oneToMany relationship with Step which is marked with orphanRemoval = True.

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinTable(name = "JOB_STEP")
private List<Step> steps;

Expected behavior is when a certain step is removed from steps list, DELETE queries should be executed on STEP and JOB_STEP tables.


First case, the expected behavior occurs when following code is executed:

Job job = new Job("Test");
Step step = new Step("Test");
job.addStep(step);
repository.save(job);
job.removeStep(step);
repository.save(job);

I see three expected log messages:

o.h.e.i.AbstractFlushingEventListener: Flushed: 0 insertions, 0 updates, 1 deletions to 2 objects
org.hibernate.SQL: delete from job_step where job_id=?
org.hibernate.SQL: delete from step where id=?

Second case, when orphanRemoval = true doesn’t invoke the deletion of orphans from the DB.

Job job = new Job("Test");
Step step = new Step("Test");
repository.save(job); //This causes the bug to happen
job.addStep(step);
repository.save(job);
job.removeStep(step);
repository.save(job);

After the above code is executed, I can still see entries in STEP and JOB_STEP tables in the DB.

Following log is printed: Flushed: 0 insertions, 0 updates, 0 deletions to 2 objects


I’ve been trying to find the root cause of this problem for few weeks now through debugging the Hibernate’s source code. But it didn’t really help. However, I noticed few abnormal things that might be helpful for you:

1) During debugging, I stumbled upon this method resetStoredSnapshot from org.hibernate.engine.spi.CollectionEntry that essentially just wipes the stored snapshot of Steps that later on causes Hibernate not to find orphans. While in the first case, when Hibernate works as expected, resetStoredSnapshot is not executed at all.

2) I noticed that java.util.List of Steps starts working aberrantly once it gets converted to org.hibernate.collection.PersistentList by Hibernate


The workspace with reproduced bug is here: https://github.com/yeralin/ReproduceBug


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.