1

I have JPA entity Customer having say 50 fields and I would like to update it from the end user using html form.

I am passing one instance of entity to html page form (using thymeleaf), this form is having only 20 fields out of 50 (including ID field). Now once the form is submitted, I would like to update 20 fields from data received using form to the database. I am not getting solution for above issue. One solution is to update individual field but I don't think it is good solution.

@Entity
public class Customer
{
 ...
50 fields
}

My get method:

@GetMapping(value = "customer")
    public String customer(Model model) {
          Customer customer = null;
        Optional<Customer> optional = customer Repo.findById(customerId);

        if (optional.isPresent()) {
            customer = optional.get();
        }
        model.addAttribute("customer", Customer);
        return "customer";
    }

Html form:

  <form action="updateCustomer">
    ----20 fields which I would like to get update from user are here
    </form>



@PostMapping(value = "updateCustomer")
public String updateCustomer(Model model, @ModelAttribute Customer customer) {
    if(customer==null) {
        System.out.println("Customer object is null");
    }
    else
    {
        customerRepo.save(customer);
    }
    return "savedCustomer";

}

In the post method when I get customer object it is having only 20 fields data not 50(Customer entity is having total fields) because html form is having only 20 fields for update. How to update the old customer object having 50 fields using the new customer object having updated 20 fields.?

Galaxy
  • 743
  • 1
  • 8
  • 26
  • 1
    There's not enough information here to help I don't think. What's wrong with updating your fields besides it being tedious to code? What types of values are they getting (derived from other data or static)?. – CollinD Mar 15 '18 at 17:04
  • @CollinD more details provided in the question. Please take a look. – Galaxy Mar 15 '18 at 17:13
  • 1
    So, to clarify, you want to basically take a `Customer` from the database, and overwrite its 20 fields with data from your form (ie: left merge with your new `@ModelAttribute Customer`), and then save that? – CollinD Mar 15 '18 at 17:23
  • @CollinD Yes. You are right. Basic way to call 20 setters of individual field. But I think there could be better solution to this. – Galaxy Mar 15 '18 at 17:25
  • 1
    In that case, check out https://stackoverflow.com/questions/24865923/how-to-merge-two-complex-objects-in-java There is some built-in functionality to manage this in Spring's BeanUtils class. I can't speak to how customizeable and safe it is, but it is likely possible. However if this is all just to save some typing, it may be worth considering skipping the added complexity. – CollinD Mar 15 '18 at 17:35
  • @CollinD Thanks – Galaxy Mar 17 '18 at 03:55

3 Answers3

1

There are three ways in the past that I solved this problem

1) have the page GET the Customer object in question, use the object to pre-populate the form, and then POST the changed customer object. The benefit is that the user changing the Customer sees all info related to the Customer, and you have a easy merge on the backend. The drawback is an additional REST call.

2) Create a DTO, and transfer non-null fields from the DTO to the entity. The benefit is you don't have to update all the fields in the form, and no extra network call. the drawback is that it's a pure pain in the rear end.

3) Create a DTO, and make it an entity to save. The benefit is that it's a easy merge back to the database, nothing prevents you from mapping the same table and fields to multiple entities. The drawback is that you have to worry about concurrency issues, which may just not work in your workflow, and the DTO is basically specific per form.

Jeff Wang
  • 1,837
  • 1
  • 15
  • 29
0

To make partial updates to entity, you either need to use Criteria API or JPQL query ... this is called projection in JPA, here is a quick example , Note : You might not be able to use this feature if you are using an old version of JPA query parser (no JPQL updates) + old version of JPA (when no CriteriaUpdate lib was there) you will then need to fetch the object from DB with the id passed from the client, update the 20 properties from the client and save the changes back

osama yaccoub
  • 1,884
  • 2
  • 17
  • 47
0

Below solution worked for me:

Helper Class:

public class BeanCopy {

private static final Set<Class<?>> primitiveTypes = new HashSet<Class<?>>(
        Arrays.asList(Boolean.class, Character.class, Byte.class, Short.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Void.class, String.class, Date.class));

public static void nullAwareBeanCopy(Object dest, Object source) throws IllegalAccessException, InvocationTargetException
{
    new BeanUtilsBean() {
        @Override
        public void copyProperty(Object dest, String name, Object value)
                throws IllegalAccessException, InvocationTargetException {
            if(value != null &&   (primitiveTypes.contains(value.getClass()) )) {
                super.copyProperty(dest, name, value);
            }
        }
    }.copyProperties(dest, source);
}

}

This is how I copied and forced changes to database:

 try {
            BeanCopy.nullAwareBeanCopy(DBcustomer,customer);
            customerRepo.save(DBcustomer);

        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

Please let me know any better solution is available for the above problem.

Galaxy
  • 743
  • 1
  • 8
  • 26
  • 2
    If you do this, what if you wanted to blank out a field by setting it to null? – Vasan Mar 16 '18 at 16:48
  • @Vasan I think We can remove “not equal to null “condition and will pass array of fields which are received with http request to constrain the update only for those field irrespective of their value. Is this concept will work? – Galaxy Mar 17 '18 at 03:55