2014-01-17 91 views
15

从书临EJB3 JPA:在Java EE应用程序合并VS找到更新实体JPA

来处理最常见的策略本(-update实体 - )使用JPA是将结果的变化为分离的实体实例,并合并未决的改变成一个持久性上下文,以便它们可以被写入到数据库

实施例: EMP参数是一个分离ë ntity

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

然后说:

如果信息被udated量是非常小的,我们能避免分离的对象,并通过定位托管版本和手动复制合并()操作完全进入它的变化。

例子: 这里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()

好的,但是为什么

+0

数据库访问对于较大的对象来说是很昂贵的,因此它应该在分离模式下完成,以确保您不会对后端进行不必要的调用。 – hd1

+0

而不是“emp.setEmpName(newName);”逐个设置字段。可以通过“emp = new Employee(//设置字段)”来完成吗? @请让我出来 –

+0

是的,实际上setter/getters是规范可选的,你可以在构造函数上初始化参数或者使用流利的API,JPA会找到这些值。谨慎使用它;) – Sergio

回答

11

因为如果你的bean有很多属性,JPA将在合并过程中逐个检查所有属性,如果你正在处理一个分离的对象。现在,如果你有一个200个atrributes并且只想改变1个字段的bean,那么JPA更容易获得托管版本(在内部,JPA知道何时管理实体的一个字段是“脏的”或者不),那么它只会处理那个特定的属性。

+2

显然这是依赖于实现的。某些JPA实现(例如DataNucleus JPA)使用字节码增强并添加一个字段,用于存储持久字段是否在分离时被修改,因此attach(合并)过程非常高效。 – DataNucleus

+0

如果我反思修改实体的字段(从而绕过方面/字节码增强),那该怎么办?从DataNucleus和Hibernate JPA的角度来看? –