Question

I have a relation n-n mapped with these 3 entities :

@Entity
public class ApplicatifDo {
   .....
   @OneToMany(cascade = CascadeType.ALL, mappedBy = "applicatifDo", fetch = FetchType.EAGER, orphanRemoval = true)
   private Set<ApplicatifTerminalDo> applicatifTerminalSet;
   .....
}

@Entity
public class ApplicatifTerminalDo {
   ......
   @ManyToOne
   @JoinColumn(name = "idApplicatif", nullable = false)
   private ApplicatifDo applicatifDo;
   @ManyToOne
   @JoinColumn(name = "idTerminal", nullable = false)
   private TerminalDo terminalDo;

   @Column
   private String remarques;
   ......
}

@Entity
public class TerminalDo {
   ......
   @OneToMany(cascade = CascadeType.ALL, mappedBy = "terminalDo", fetch = FetchType.EAGER, orphanRemoval = true)
   private Set<ApplicatifTerminalDo> applicatifTerminalSet;
   ......
}

I try to do a test where I have an ApplicatifDo persisted which contains many ApplicatifTerminalDo in its Set, and I change some values of these, remove others, add new ones in this Set :

modifyRemarques(firstElement(applicatifDo.getApplicatifTerminalSet()));
applicatifDo.getApplicatifTerminalSet.add(anotherApplicatifTerminal);
applicatifDo.getApplicatifTerminalSet.remove(onceApplicatifTerminal);

Then when I merge that in my DB, in my join-table ApplicatifTerminal I see the modification of "Remarques" appearing, as well as the new ApplicatifTerminal entities appearing, but the remove doesn't work, and the entities that should be deleted are still present in my join-table (and I use orphanRemoval).

And I get no error in the console when I test that, but still the remove entities shouldn't be in DB anymore.

PS : I used the same method on a 1-n relation and the cascading of all types of modification on a contained Set of entities in a parent entity were working well (remove included).

Update :

I tried to remove the onceApplicatifTerminal from the TerminalDo as said by Chris, but still doesn't work. Here is the code :

            Iterator<ApplicatifTerminalDo> iterator = applicatifDo
                .getApplicatifTerminalSet().iterator();
            boolean first = true;
            while (iterator.hasNext()) {
                ApplicatifTerminalDo element = iterator.next();
                if (!first) {
                    element.setRemarques("remarques updated");
                } else {
                    iterator.remove();
                    element.getTerminalDo().setApplicatifTerminalSet(
                            applicatifDo.getApplicatifTerminalSet());
                    first = false;
                }
            }

Here I try to remove the first ApplicatifTerminalDo from the list and update a column value for others. And when I merge, the values are changed but the remove doesn't work, even if I get the TerminalDo to remove put the updated ApplicatfTerminal Set.

Is it possible to achieve what I want to do ? What is the best practice for updating/removing rows from a personnally-made join table ?

Please help, i don't understand why.

Was it helpful?

Solution

You are expecting the orphan removal to kick in because you have dereferenced onceApplicatifTerminal, and want onceApplicatifTerminal.

Orphan removal has draw backs, which are hinted at when it is called private ownership in other ORMs: the entity really should only be owned privately, which is not the case here. You are running into problems when you call applicatifDo.getApplicatifTerminalSet.remove(onceApplicatifTerminal); because there exists a TerminalDo instance that also references this onceApplicatifTerminal instance. JPA has allows the use of caching, so unless this TerminalDo->onceApplicatifTerminal is also cleaned up in your entities, it is left with a reference to the onceApplicatifTerminal entity, and because of your cascade Persist/Merge settings, this causes it to be resurrected. Just removing the cascade settings on the TerminalDo->ApplicatifTerminalDo, as if the reference isn't removed, the cache will still be left referencing this non-existing entity.

Orphan removal should be used carefully and only on relationships where the referenced entity is not referenced by other entities, or care needs to be taken to clean up these references beforehand.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top