为什么merge()返回复制对象?

时间:2019-09-17 13:28:02

标签: hibernate jpa jpa-2.0 jpa-2.1

我是JPA的新手,请阅读EntityManager中提供的merge方法,当我们尝试合并一个分离的对象时,该方法会返回一个复制对象。 为什么返回一个复制对象?

我试图分离一个托管对象,发现分离对象的哈希码与merge方法返回的对象的哈希码不同。

Employee emp = new Employee();
emp.setName("Name");

em.persist(emp);

emp = em.find(Employee.class, emp.getId());
em.detach(emp);

emp.setName("New Name");

int empHashCode = emp.hashCode();

Employee managedEmp = em.merge(emp);
int managedHashCode = managedEmp.hashCode();

if(empHashCode == managedHashCode){
    System.out.println("Hash Code Equal");
} else{
    System.out.println("Hash Code not Equal");
}

输出为“哈希码不相等”。 这意味着两个对象都不相同,但是为什么呢?

2 个答案:

答案 0 :(得分:5)

merge()返回复制对象,请找到以下说明

  

当由持久性上下文管理实体时,应用程序可能无法直接从多个线程访问该实体。但是,应用程序可以选择允许在实体分离时同时访问它们。如果选择这样做,则必须通过实体上编码的方法来控制同步。但是,不建议使用并发实体状态访问,因为实体模型不能很好地适合于并发模式。最好是简单地复制实体,然后将复制的实体传递给其他线程进行访问,然后在需要持久化时将所有更改合并回持久性上下文中。

以上说明摘自“ Java EE 8中的Pro JPA 2:Java持久性API深入指南”

答案 1 :(得分:2)

除了@ yashjain12yj添加的答案

要考虑的情况很多。

  • 如果该实体已经在持久性上下文(会话)中,则除了级联之外不执行任何操作
  • 如果实体是分离的,则返回一个副本(对象),该副本已附加(托管)
  • 如果实体是临时实体(新实例),则将其保存并返回持久(和托管)副本
  • 如果实体已分离,但当前实体管理器中存在具有相同标识符的对象,则将分离对象的状态复制到当前持久性实体中,并返回它(当前)

更多详细信息here