2

I have implemented by project using Spring-Data-Rest. I am trying to do an update on an existing record in a table. But when I try to send only a few fields instead of all the fields(present in Entity class) through my request, Spring-Data-Rest thinking I am sending null/empty values. Finally when I go and see the database the fields which I am not sending through my request are overridden with null/empty values. So my understanding is that even though I am not sending these values, spring data rest sees them in the Entity class and sending these values as null/empty. My question here is, is there a way to disable the fields when doing UPDATE that I am not sending through the request. Appreciate you are any help.

Update: I was using PUT method. After reading the comments, I changed it to PATCH and its working perfectly now. Appreciate all the help

7
  • 2
    instead of using put use patch method Commented Feb 7, 2019 at 17:14
  • This is not related to spring-data; this is how JPA/Hibernate works. If you try to update by passing an entity, all the not filled fields will be considered as null and so the update will be null. You should use HQL o JPQL instead Commented Feb 7, 2019 at 17:14
  • What HTTP method do you use to update your entity? PUT or PATCH? Commented Feb 7, 2019 at 18:03
  • 1
    @Cerp0 it depends on your needs, PUT has the main goal o "putting" the entire resource somewhere (all the fields of an entity), and PATCH will just send the values you need to "patch" something (just one or two fields of the entity for example) Commented Feb 7, 2019 at 18:28
  • @AngeloImmediata While JPA/Hibernate may also use such a semantic, considering updates via PUT it's the HTTP specification that actually states that a payload received via PUT should replace the current representation. So Spring just does what the specification intents Commented Feb 8, 2019 at 16:19

3 Answers 3

1

Before update, load object from database, using jpa method findById return object call target. Then copy all fields that not null/empty from object-want-to-update to target, finally save the target object.

This is code example:

public void update(Object objectWantToUpdate) {

    Object target = repository.findById(objectWantToUpdate.getId());
    copyNonNullProperties(objectWantToUpdate, target);

    repository.save(target);
}

public void copyNonNullProperties(Object source, Object target) {
    BeanUtils.copyProperties(source, target, getNullPropertyNames(source));
}

public String[] getNullPropertyNames (Object source) {

    final BeanWrapper src = new BeanWrapperImpl(source);
    PropertyDescriptor[] propDesList = src.getPropertyDescriptors();

    Set<String> emptyNames = new HashSet<String>();

    for(PropertyDescriptor propDesc : propDesList) {
        Object srcValue = src.getPropertyValue(propDesc.getName());

        if (srcValue == null) {
            emptyNames.add(propDesc.getName());
        }
    }

    String[] result = new String[emptyNames.size()];
    return emptyNames.toArray(result);
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks @Tran Quoc Vu, I like your answer. For now I am not using this solution since it involves adding a new custom controller. I am going with using PATCH instead of using PUT for now. But I may come back to this if I see the use for a custom controller.
0

You can write custom update query which updates only particular fields:

@Override
public void saveManager(Manager manager) {  
    Query query = sessionFactory.getCurrentSession().createQuery("update Manager set username = :username, password = :password where id = :id");
    query.setParameter("username", manager.getUsername());
    query.setParameter("password", manager.getPassword());
    query.setParameter("id", manager.getId());
    query.executeUpdate();
}

Comments

0

As some of the comments pointed out using PATCH instead of PUT resolved the issue. Appreciate all the inputs. The following is from Spring Data Rest Documentation:

"The PUT method replaces the state of the target resource with the supplied request body.

The PATCH method is similar to the PUT method but partially updates the resources state."

https://docs.spring.io/spring-data/rest/docs/current/reference/html/#customizing-sdr.hiding-repository-crud-methods

Also, I like @Tran Quoc Vu answer but not implementing it for now since I dont have to use custom controller. If there is some logic(ex: validation) involved when updating the entity, I am in favor of using the custom controller.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.