merge vs find更新实体JPA

Ser*_*gio 17 java persistence jpa java-ee

Pro EJB3 JPA一书中:

在使用JPA的Java EE应用程序中处理此(-update实体)的最常见策略是将更改的结果放入分离的实体实例中,并将挂起的更改合并到持久性上下文中,以便将它们写入数据库

例如: 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,说:

如果使用的信息量非常小,我们可以通过查找托管版本并手动将更改复制到其中来完全避免分离对象和merge()操作.

示例: 此处附有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);
}
Run Code Online (Sandbox Code Playgroud)

因此,看起来像小更新和创建操作策略find()然后逐个设置新值是方便的.但是!对于数据的大更新(即集合)是首选的,有一个分离的实体和所有它的关系(与CascadeType.Merge)并做大merge().

好的,但为什么呢?

小智 13

因为如果你的bean有很多属性,如果你正在处理一个分离的对象,JPA将在合并过程中逐个检查所有属性.

现在,如果你有一个包含200个特征的bean并且只想更改1个字段,那么JPA更容易获得托管版本(在内部,JPA知道托管实体的一个字段何时"脏"),那么它只会处理那个特定的属性.

  • 显然这是依赖于实现的.一些JPA实现(例如DataNucleus JPA)使用字节码增强并添加一个字段来存储是否在分离时修改了持久字段,因此附加(合并)过程非常有效. (2认同)