Merge vs find для обновления объектов JPA

Из книги Pro EJB3 JPA:

Наиболее распространенная стратегия для обработки этого (-update entities-) в приложении Java EE, использующего JPA, заключается в том, чтобы поместить результаты изменений в отдельные экземпляры сущности и объединить ожидающие изменения в контекст персистентности, чтобы они могли быть записаны в базу данных

Пример: Параметр emp - это отдельный объект

@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);
    }
}

Затем, говорит:

Если количество информации, которая была ограничена, очень мала, мы можем полностью исключить операцию отдельного объекта и слияния(), установив управляемую версию и вручную скопировав в нее изменения.

Пример: Здесь emp прикреплен

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);
}

Итак, выглядит для небольших обновлений и создает операции по стратегии find(), а затем задавать новые значения один за другим. Но!, для больших обновлений данных (например, коллекций) предпочтительнее иметь отдельный объект и все его отношения (с CascadeType.Merge) и сделать большой merge().

ОК, но почему?

Ответы

Ответ 1

Потому что, если ваш bean имеет множество атрибутов, JPA будет проверять один за другим в процессе слияния для всех атрибутов, если вы имеете дело с отдельным элементом.

Теперь, если у вас есть bean с 200 атрибутами и вы хотите изменить только одно поле, JPA упростит просто получить управляемую версию (внутренне JPA знает, когда одно поле управляемой сущности "грязно" "или нет), тогда он будет иметь дело только с этим конкретным атрибутом.