有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

重新保存修改过的对象时,java JPA merge()无法按预期工作

这是我为实体设置的:

@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
}

当我向电影列表中添加新的Actor时,我能够成功地调用entityManager.merge()。以下操作成功地保存了这些表

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

然后我想更新演员的名字,所以我要做的就是这样。我无法更新已保存/现有的参与者:

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

上面的方法不起作用,我可以看到对象在调试模式下被更新,但是当调用merge()时,它不会更新数据库

我哪里做错了?我认为合并将更新,如果已经存在


共 (2) 个答案

  1. # 1 楼答案

    请参阅EntityManager接口的方法flush()的javadoc。您可以使用它将持久性上下文同步到基础数据库

    如果FlushModeType被设置为COMMIT,那么底层数据库将在整个事务提交时更新。要解决这个问题,可以setFlushModeAUTO (Default)刷新每个查询。或者,您可以将代码的某些部分包装到NESTEDtransaction中,只刷新这一部分。您还可以在当前事务中定期调用flush()方法:

    entityManager.flush();
    entityManager.clear();
    
  2. # 2 楼答案

    整个管理者merge()操作用于将对分离对象所做的更改合并到持久性上下文中merge不会直接将对象更新到数据库中,它会将更改合并到持久性上下文(事务)中

    transaction被提交时,或者如果持久性上下文被刷新,那么对象将在数据库中更新

    对你来说merge不是必需的,尽管它经常被误用。要更新一个对象,只需read它,然后change通过它的set方法更新它的状态,然后提交transactionEntityManager将找出所有已更改的内容,并更新数据库^只有当有persistence对象的分离副本时,{}才是必需的

    只是在你的情况下,你没有做事务提交

    entityManager.getTransaction().commit();