Jpa: Update Only Specific Fields

How to update only particular fields in an entity using springbooot JPA update API

This is not really springboot jpa problem. The issue is in the way updateBook method in service has been implemented. The updateBook method is setting all the fields from dto on persisted book entity without checking if the dto.get* returns null or not.

Very simply but crude solution to this problem would be to have if(dto.get* != null) check for each field before setting the value in book entity. i.e.

if (bookDto.getBookAuthor() != null) 
book.setBookAuthor(bookDto.getBookAuthor());
if (bookDto.getBookLanguage() != null)
book.setBookLanguage(bookDto.getBookLanguage());
if (bookDto.getBookPrice() != 0)
book.setBookPrice(bookDto.getBookPrice());
...

This leaves the updateBook service method generic to allow updating one or more fields without worrying about others being overwritten. If this makes your service method too noisy the dto to entity conversation part can be extracted into its own method for clarity.

For more advance usecases and if your entity/dto has more than a handful fields or nested objects as fields then this becomes cumbersome. In such scenarios you may want to handcraft a separate implementation which perhaps uses reflection to map fields from dto to entity if the field value is not null. The usage of reflection is however likely to be slow and/or error prone if not done properly.

There are however libraries and frameworks for more regular usecases which makes such conversation easier. At the simplest springframework's BeanUtils.copyProperties method provides a way to map values from one object to another and the last argument of ignored properties can be used to provide fields names to be ignored. This stackoverflow answer shows how to write a generic method that creates a list of property names to ignore if they are null in source object; and they uses this list to pass as parameter in BeanUtils.copyProperties.

public static String[] getNullPropertyNames (Object source) {
final BeanWrapper src = new BeanWrapperImpl(source);
PropertyDescriptor[] pds = src.getPropertyDescriptors();

Set<String> emptyNames = new HashSet<>();
for(PropertyDescriptor pd : pds) {
Object srcValue = src.getPropertyValue(pd.getName());
if (srcValue == null) emptyNames.add(pd.getName());
}
return emptyNames.toArray(new String[0]);
}

then in your service method;

Book book = bookRepository.findById(bookDto.getBookId())
.orElseThrow(() -> new DataNotFoundException("Book not found"));
BeanUtils.copyProperties(bookDto, book, getNullPropertyNames(bookDto));
bookRepository.save(book);

For further advanced usecases you can use frameworks such as mapstruct or modelmapper.

How to update only specific field with spring jpa repository?

I have a below Student entity and I want to update only not null
fields when I call CrudRepository save method.

You can't do this in this way because when you provide an entity to Spring or JPA for an update operation, they cannot guess why some fields of this entity are null : is it null because you want to set the field to null ? Or is is null because you have not fulfilled this field but you don't want that the existing value to be overwritten ?

So, they don't make guesworks and simply update the row with effective values in the fields of your entity.

So you should write a JPQL Query where you explicit fields to update :

UPDATE Student e SET e.name=%1 AND e.number=%2
WHERE ...

Updating one field in JPA entity

Do I need to do a findById then update the specific field then do the merge

That would be the regular approach, except that you don't need to merge a managed entity, just let JPA detect the changes and update it automatically.

or is there a way to tell the to only update that field?

No. But you could use a "short" version of your User (with only the field(s) to update). Another option would be to use a Bulk Update Operation but this is IMO really not a good use case. I wouldn't use this approach.

Reference

  • JPA 1.0 specification

    • 4.10 Bulk Update and Delete Operations


Related Topics



Leave a reply



Submit