Reputation: 16628
Stuck on the same problem Is there any method to ignore null
values when updating the database in Hibernate
?
Whenever you call update(); of Session, it will also update the null values found in the object.
Example:
User user = new User();
user.setUserId(5);
user.setUserName("Maarten");
user.setUserFirstName(null); // but in database this value is not null
session.update( user);
OR
session.saveOrUpdate( user);
The DB will now update the user, but will set the user firstname to null (because it is null in the object).
Is there any way or method in Hibernate to avoid this (I don't want to fire a select/ update query to set the bean)? that it will ignore the null value?
Upvotes: 16
Views: 27581
Reputation: 1
This works for me
@Data
public class ProductRequest {
private Optional<String> name;
private Optional<String> unitSale;
}
The most important thing here is to use Optional<> in the DTO class, because Jackson when deserializing distinguishes between an explicit null in the request body and a null due to the omission of the parameter in the request.
Example:
If we make the following PUT request with parameters
http put localhost:8080/products/200 name=banana unit_sale=KG
We obtain the following DTO
ProductRequest(name=Optional[banana], unitSale=Optional[KG])
And when we send an explicit null value:
http put :8080/products/200 name=banana unit_sale:=null
ProductRequest(name=Optional[banana], unitSale=Optional.empty)
And when we send some parameters omitting the others
http put :8080/products/200 name=banana
ProductRequest(name=Optional[banana], unitSale=null)
And that's the key, distinguishing between Optional.empty and null in our business logic to determine what value to set in our entity.
@Transactional
public void update(Long productId, @Valid ProductRequest productRequest) {
ProductEntity productEntity = productRepository.findByIdOptional(productId)
.orElseThrow(() -> new EntityNotFoundException("Product ID not found"));
if (productRequest.getName() != null) {
productEntity.name = unwrapOptional(productRequest.getName());
}
if (productRequest.getUnitSale() != null) {
productEntity.unitSale = unwrapOptional(productRequest.getUnitSale());
}
}
public <T> T unwrapOptional(final Optional<T> o) {
return o.isPresent() ? o.get() : null;
}
Upvotes: 0
Reputation: 16628
One of the options is, load
the bean using get(object)
method from the session and then set/change the values. But this comes with an overhead of one extra call to the database. Or you can create a custom query if making an extra call is crucial.
Edit: if bean
is cached then get(object)
will not be a performance hit.
Upvotes: 1
Reputation: 84
It depends on the abstraction level you wish to control, and the business rules of the object:
If, anyway, you define your requisites in a lower level, e.g. "do not include null values in update queries", you can use the following:
Upvotes: 1
Reputation: 786
The dynamic-update attribute tells Hibernate whether to include unmodified properties in the SQL UPDATE statement.
Upvotes: 2