Well the question pretty much says everything. Using JPARepository how do I update an entity?
JPARepository has only a save method, which does not t
You can simply use this function with save() JPAfunction, but the object sent as parameter must contain an existing id in the database otherwise it will not work, because save() when we send an object without id, it adds directly a row in database, but if we send an object with an existing id, it changes the columns already found in the database.
public void updateUser(Userinfos u) {
User userFromDb = userRepository.findById(u.getid());
// crush the variables of the object found
userFromDb.setFirstname("john");
userFromDb.setLastname("dew");
userFromDb.setAge(16);
userRepository.save(userFromDb);
}
Identity of entities is defined by their primary keys. Since firstname
and lastname
are not parts of the primary key, you cannot tell JPA to treat User
s with the same firstname
s and lastname
s as equal if they have different userId
s.
So, if you want to update a User
identified by its firstname
and lastname
, you need to find that User
by a query, and then change appropriate fields of the object your found. These changes will be flushed to the database automatically at the end of transaction, so that you don't need to do anything to save these changes explicitly.
EDIT:
Perhaps I should elaborate on overall semantics of JPA. There are two main approaches to design of persistence APIs:
insert/update approach. When you need to modify the database you should call methods of persistence API explicitly: you call insert
to insert an object, or update
to save new state of the object to the database.
Unit of Work approach. In this case you have a set of objects managed by persistence library. All changes you make to these objects will be flushed to the database automatically at the end of Unit of Work (i.e. at the end of the current transaction in typical case). When you need to insert new record to the database, you make the corresponding object managed. Managed objects are identified by their primary keys, so that if you make an object with predefined primary key managed, it will be associated with the database record of the same id, and state of this object will be propagated to that record automatically.
JPA follows the latter approach. save()
in Spring Data JPA is backed by merge()
in plain JPA, therefore it makes your entity managed as described above. It means that calling save()
on an object with predefined id will update the corresponding database record rather than insert a new one, and also explains why save()
is not called create()
.
This is how I solved the problem:
User inbound = ...
User existing = userRepository.findByFirstname(inbound.getFirstname());
if(existing != null) inbound.setId(existing.getId());
userRepository.save(inbound);
As what has already mentioned by others, the save()
itself contains both create and update operation.
I just want to add supplement about what behind the save()
method.
Firstly, let's see the extend/implement hierarchy of the CrudRepository<T,ID>
,
Ok, let's check the save()
implementation at SimpleJpaRepository<T, ID>
,
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
As you can see, it will check whether the ID is existed or not firstly, if the entity is already there, only update will happen by merge(entity)
method and if else, a new record is inserted by persist(entity)
method.
public void updateLaserDataByHumanId(String replacement, String humanId) {
List<LaserData> laserDataByHumanId = laserDataRepository.findByHumanId(humanId);
laserDataByHumanId.stream()
.map(en -> en.setHumanId(replacement))
.collect(Collectors.toList())
.forEach(en -> laserDataRepository.save(en));
}
spring data save()
method will help you to perform both: adding new item and updating an existed item.
Just call the save()
and enjoy the life :))