简体   繁体   中英

JPA merge() doesn't work as expected when resaving a modified object

This is my set up for the entity:

@Entity
@Getter
@Setter
@Table(name = "movies", schema = "public")
public class Movie {
    @Id
    @Column(name = "id")
    private UUID movieId;

    @OneToMany(mappedBy = "actor", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Set<Actors> actors = new HashSet<>();

    //Getters and setters
    }
}
@Entity
@Getter
@Setter
@Table(name = "actors_movies", schema = "public")
public class ActorMovie {
    @EmbeddedId
    private ActorId id;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("movieId")
    @JoinColumn(name = "id_movie_movie")
    private Movie movie;

    //Getters and setters below
}

I am able to successfully call entityManager.merge() when I add a new Actor to the list of movie. The following successfully persists the tables.

Movie movie = getMovieById(id);
movie.setActors(new Actor());
entityManager.merge(movie);

Then I want to update the actor name so what I do is this. I am NOT able to update an already persisted/existing Actor:

Movie movie = getMovieById(id);
movie.getActors().get(0).setName("New Name");
entityManager.merge(movie);

The above doesn't work, I can see the object being updated in debug mode but when merge() is called it doesn't update the database.

Where am I going wrong? I thought merge would update if already existing.

The EntityManager. merge() operation is used to merge the changes made to a detached object into the persistence context. merge does not directly update the object into the database, it merges the changes into the persistence context (transaction).

When the transaction is committed, or if the persistence context is flushed, then the object will be updated in the database.

For you merge is not required, although it is frequently misused. To update an object you simply need to read it, then change its state through its set methods, then commit the transaction . The EntityManager will figure out everything that has been changed and update the database. merge is only required when you have a detached copy of a persistence object.

Just in your case you arent doing commit of transaction.

entityManager.getTransaction().commit();

See the javadoc of the EntityManager interface's method flush() . You can use it to synchronize the persistence context to the underlying database .

If the FlushModeType is set to COMMIT then underlying database is updated at the time of whole transaction commit. To resolve this you can setFlushMode to AUTO (Default) to flush each query. Or you can wrap some part of your code into NESTED transaction to flush only this part. Also you can periodically invoke the flush() method inside current transaction:

entityManager.flush();
entityManager.clear();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM