我正在用Quarkus和Hibernate开发一个REST API。现在我必须创建一个端点,它接受PUT请求来更新一个现有的实体。该请求包含整个实体,以及它在数据库中的对应ID。
资源终结点:
@PUT
@Path("/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Settings update(@Valid Settings settings) {
return settingRepository.update(settings);
}
存储库类方法:
@Transactional
public Settings update(Settings settings) {
// This is just for test purposes, other methods like
// entityManager.merge() did not work although it has the PK, bc it is not "attached"
// If i pass the object to merge() without the PK, a new PK is generated.
entityManager.unwrap(Session.class).update(settings);
return settings;
}
因此,端点将收到数据库Map实体的解析POJO。问题是,此实体对象未“附加”,并且似乎merge
和EntityManager
的persist
函数都没有做我需要的事情。我需要传递对象,并根据当前主键更新它。
我试着查看了hib的Session
类,因为它包含了更多的实用函数,如update
、saveOrUpdate
等,但这些函数会导致错误,如主键的唯一约束psql异常-这让我认为它是在尝试执行INSERT而不是更新。
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "settings_pkey"
Detail: Key (id)=(1) already exists.
当然,我可以简单地创建一个手动DQL查询并将所有成员作为参数传递,但从开发人员的Angular 来看,这似乎效率很低。必须有一个简单直接的方法来完成这个看似常见的任务??在EntityManager
中没有方法只使实体“托管/附加”而没有任何副作用,所以它不会导致合并问题。我也不想首先必须通过PK从DB中选择实体,然后更改它,然后将更改保存回来。看起来像是一个不必要的往返。
1条答案
按热度按时间68bkxrlz1#
这就是Hibernate的工作原理。在您的情况下,您需要首先使用EntityManager.find()从数据库中读取实体(通过id)。然后将除id之外的所有属性替换为请求中的属性。然后使用EntityManager.merge()将修改后的实体存储到数据库中。
只是一个提示:有了Spring框架,使用CrudRepository会容易得多。