I am developing a REST API with Quarkus and Hibernate. I now have to create an endpoint which accepts a PUT request to update an existing entity. The request contains the entire entity, with its corresponding ID in the database.
Resource endpoint:
@PUT
@Path("/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Settings update(@Valid Settings settings) {
return settingRepository.update(settings);
}
Repository class method:
@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;
}
So the endpoint will receive a parsed POJO for the database mapped entity. The problem is, this entity object is not "attached" and it seems neither the merge
nor the persist
function of EntityManager
do what i need. I need to pass the object and for it to be UPDATED based on the primary key present.
I tried looking at the Session
class of hibernate, since it contains more utility functions like update
, saveOrUpdate
etc., but those result in error like unique constraint psql exceptions for the primary key - which makes me think it is tryinf to perform an INSERT rather than an update.
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "settings_pkey"
Detail: Key (id)=(1) already exists.
Of course, i could simply create a manual DQL query and pass all of the members as parameters, but this seems oddly inefficient from a developer POV. There has to be an easy and straightforward way for this seemingly common task? There is no method in EntityManager
to only make an entity "managed/attached" without any side effects so it just doesnt cause issues with merge. I also do not want to first have to SELECT the entity from the DB by PK, then change it, then save the change back. Seems like an unnecessary roundtrip.
This is how Hibernate works. In your case you will need to read the entity from the database first (by id). With EntityManager.find(). Then replace all properties other then id with the ones from the request. Then store the modified entity in the database with EntityManager.merge().
Just a hint: with Spring Framework it would be much easier using CrudRepository.