17

From the book Pro EJB3 JPA:

The most common strategy to handle this (-update entities-) in Java EE application that uses JPA is to place the results of the changes into detached entity instances and merge the pending changes into a persistence context so that they can be written to the database

Example: The emp param is a detached entity

@Stateless
public class EmployeeServiceBean {
    @PersistenceContext
    EmtityManager em;

    public void updateEmployee(Employee emp){
       if(em.find(Employee.class, emp.getId()) == null){
           throw new IllegalArgumentException("Unknown Employee id")
       }

       em.merge(emp);
    }
}

Then, says:

If the amount of information being udated is very small, we can avoid the detached object and merge() operation entirely by locating the managed version and manually copying the changes into it.

Example: Here the emp is attached

public void updateEmployee(int id, String newName, long newSalary) {
    Employee emp = em.find(Employee.class, id);
    if(emp==null){
        throw new IllegalArgumentException("Unknown Employee id")
    }
    emp.setEmpName(newName);
    emp.setSalary(newSalary);
}

So, looks like for small updates and create operations the strategy find() and then set new values one by one is convenient. But!, for big updates of data (i.e collections) is preferred have a detached entity and all it's relations (with CascadeType.Merge) and do a big merge().

OK, but why?

Sergio
  • 3,317
  • 5
  • 32
  • 51
  • Database access is expensive for larger objects and so it should be done in detached mode to ensure you don't make unnecessary calls to the backend. – hd1 Jan 17 '14 at 00:16
  • instead of " emp.setEmpName(newName); " setting the field one by one. Can it be done by " emp = new Employee( //setting up fields ); "? @Please let me out – Weishi Z Aug 12 '15 at 00:18
  • yes, in fact setters/getters are optional by the spec, you could initialize parameters on the constructor or with a fluent API and JPA will find the values. Use it with precaution ;) – Sergio Aug 12 '15 at 01:14
  • Your question is my answer, thanks. – The Student Nov 16 '18 at 21:12

1 Answers1

12

Because if your bean has a lot of attributes, JPA will check one by one in the merge process, for all attributes, if you're dealing with a detached object.

Now, if you have a bean with 200 atrributes and want to change only 1 field, it´s easier for JPA to just get the managed version (internally, JPA knows when one field of a managed entity is "dirty" or not), then it will only deal with that specific attribute.

  • 2
    clearly this is implementation-dependent. Some JPA implementations (e.g DataNucleus JPA) use bytecode enhancement and add a field that stores whether the persistent fields have been modified while detached, hence the attach (merge) process is pretty efficient. – DataNucleus Jan 17 '14 at 11:52
  • What if I reflectively modify the fields of an entity (thereby bypassing the aspects / bytecode enhancements), how does this work? From both DataNucleus and Hibernate JPA perspectives? – Sayo Oladeji May 13 '15 at 02:47