The problem is that JPA does not support both sides of a bidirectional relationship for you. This is much more obvious if you are using a JPA provider that has a second level cache. The reason is that when you establish your own side of the relationship - in this case, call moviesHasCrew.setCrew (w) and then em.flush () - this will update the FK database. But if you immediately check your object model, you will see that the crew member mentioned does not have a corresponding movieHasCrew instance in his collection. JPA does not manage your links and install them for you, so it is not synchronized with what is in the database.
This is to be expected in the same EntityManager. When a second level cache is involved, every time you request a Crew instance, it returns a cached copy, which is now deprecated.
The only way to update the collection is to reload the Crew instance from the database. This can be done by clearing the cache or force updating.
The best alternative is to maintain both sides of a bidirectional relationship and synchronize them with each other. In the code you have, this means a call:
public void addCrew(Movie m, Crew w) { MoviesHasCrew moviesHasCrew = new MoviesHasCrew(); moviesHasCrew.setCrew(w); w.addMoviesHasCrew(moviesHasCrew); moviesHasCrew.setMovy(m); m.addMoviesHasCrew(moviesHasCrew); // (1) moviesHasCrew.setRole(Role.DEFAUT_ROLE); em.persist(moviesHasCrew); em.merge(m); // noop unless it is detached em.merge(w); // noop unless it is detached }
Merging is required if they are separate instances, since the change in the collection must be placed in the EntityManager so that it can be cached.
If these merges are what you want to avoid, you can rely on MoviesHasCrew-> Movies and moviesHasCrew-> Crew to handle it for you by setting the CascadeType.MERGE parameter to this relationship, and then use em.merge (moviesHasCrew ); instead of calling 3 em. Combining moviesHasCrew will cause it to be inserted into the database in the same way as persist, but merging will cascade across all reference objects with relationships marked as CascadeType.MERGE, so Crew and Movie links will also be merged.
Chris source share