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 знает, когда одно поле управляемой сущности "грязно" "или нет), тогда он будет иметь дело только с этим конкретным атрибутом.