Hiberate 合并和刷新实体

在先前的教程中,我们了解了在 Hiberate 中使用save()saveOrUpdate()方法保存实体的知识。 从中我们了解到,在大多数情况下,您甚至都不需要那些方法,因为 hibernate 自动管理持久实体上的更新。 在大多数情况下,您只需要关心瞬态对象。 在本教程中,我将讨论有关 Hiberate 会话类中存在的refresh()merge()方法的一些想法。

使用refresh()方法刷新 Hiberate 实体

有时,我们会遇到这样的情况:我们的应用数据库被某些外部应用/代理修改,因此您的应用中的相应 Hiberate 实体实际上与其数据库表示不同步,即具有旧数据。 在这种情况下,可以使用session.refresh()方法用数据库中可用的最新数据重新填充实体。

您可以在Session接口上使用refresh()方法之一来刷新持久对象的实例,如下所示:

public void refresh(Object object) throws HibernateException
public void refresh(Object object, LockMode lockMode) throws HibernateException

这些方法将从数据库重新加载对象的属性,并覆盖它们。 在现实生活中的应用中,除了上述情况之外,您不必经常使用refresh()方法。

我们来看一个refresh()方法的示例。

public class RefreshEntityExample
{
   public static void main(String[] args)
   {
      Session sessionOne = HibernateUtil.getSessionFactory().openSession();
      sessionOne.beginTransaction();

      //Create new Employee object
      EmployeeEntity emp = new EmployeeEntity();
      emp.setEmployeeId(1);
      emp.setFirstName("Lokesh");
      emp.setLastName("Gupta");

      //Save employee
      sessionOne.save(emp);
      sessionOne.getTransaction().commit();
      sessionOne.close();

      //Verify employee's firstname
      System.out.println(verifyEmployeeFirstName(1, "Lokesh"));

      Session sessionTwo = HibernateUtil.getSessionFactory().openSession();
      sessionTwo.beginTransaction();

      //This 
      emp.setFirstName("Vikas");
      sessionTwo.refresh(emp);

      sessionTwo.getTransaction().commit();
      sessionTwo.close();

      System.out.println(emp.getFirstName().equals("Lokesh"));

      HibernateUtil.shutdown();
   }  

   private static boolean verifyEmployeeFirstName(Integer employeeId, String firstName){
      Session session = HibernateUtil.getSessionFactory().openSession();
      EmployeeEntity employee = (EmployeeEntity) session.load(EmployeeEntity.class, employeeId);
      //Verify first name
      boolean result = firstName.equals(employee.getFirstName());
      session.close();
      //Return verification result
      return result;
   }
}

Output:

true
true

查看突出显示的线条上方。

  • 第 15 行以“Lokesh”的名字保存员工
  • 第 26 行设置了名字“Vikas”。 由于实体已分离,因此不会更新数据库。
  • 第 27 行使用refresh()方法用数据库刷新实体。
  • 第 32 行验证在实体中设置的名字是否已用“Lokesh”更新,因为这是数据库当前所拥有的名字。

这全部与刷新方法有关。 让我们看另一种类似的方法merge()

使用merge()方法合并 Hiberate 实体

方法merge()refresh()的作用完全相反,即,它使用来自分离实体的值更新数据库。 刷新方法是使用最新的数据库信息更新实体。 所以基本上,两者是完全相反的。

当您希望将分离实体再次更改为持久状态时执行合并,并且将分离实体的更改迁移到(或覆盖)数据库。 合并操作的方法签名为:

Object merge(Object object)
Object merge(String entityName, Object object)

Hibernate 官方文档对merge()方法给出了很好的解释:

将给定对象的状态复制到具有相同标识符的持久对象上。 如果当前没有与该会话关联的持久化实例,则将其加载。 返回持久实例。 如果给定实例未保存,请保存的副本并将其作为新的持久实例返回。 给定的实例不与会话关联。 如果关联是用cascade="merge"映射的,则此操作将级联到关联的实例。

因此,如果我以下面的代码为例,那么下面列出的几点对您来说应该很清楚。

EmployeeEntity mergedEmpEntity = session.merge(empEntity);

  • empEntity传递给merge()方法时,它是分离的实体。
  • merge()方法将使用从empEntity获取的标识符信息搜索已加载的EmployeeEntity实例。 如果找到了这样的持久化实体,那么它将用于更新。 否则,将使用empEntity中存在的相同标识符信息将新的EmployeeEntity加载到会话中。
  • 数据从empEntity复制到新发现/加载的实体。
  • 由于新实体/发现实体是永久性的,因此从empEntity复制到该实体的所有数据都会自动保存到数据库中。
  • merge()方法返回对该新实体的引用,并将其分配给mergedEmpEntity变量。
  • empEntity仍然是独立实体。
public class MergeEntityExample
{
   public static void main(String[] args)
   {
      Session sessionOne = HibernateUtil.getSessionFactory().openSession();
      sessionOne.beginTransaction();

      //Create new Employee object
      EmployeeEntity emp = new EmployeeEntity();
      emp.setEmployeeId(1);
      emp.setFirstName("Lokesh");
      emp.setLastName("Gupta");

      //Save employee
      sessionOne.save(emp);
      sessionOne.getTransaction().commit();
      sessionOne.close();

      //Verify employee's firstname
      System.out.println(verifyEmployeeFirstName(1, "Lokesh"));

      Session sessionTwo = HibernateUtil.getSessionFactory().openSession();
      sessionTwo.beginTransaction();

      //Set new first name
      emp.setFirstName("Vikas");

      //Merge the emp object using merge() method
      EmployeeEntity mergedPersistentEmpEntity = (EmployeeEntity) sessionTwo.merge(emp);

      sessionTwo.getTransaction().commit();
      sessionTwo.close();

      //Verify employee's firstname again in database
      System.out.println(verifyEmployeeFirstName(1, "Vikas"));

      HibernateUtil.shutdown();
   }  

   private static boolean verifyEmployeeFirstName(Integer employeeId, String firstName){
      Session session = HibernateUtil.getSessionFactory().openSession();
      EmployeeEntity employee = (EmployeeEntity) session.load(EmployeeEntity.class, employeeId);
      //Verify first name
      boolean result = firstName.equals(employee.getFirstName());
      session.close();
      //Return verification result
      return result;
   }
}

Output:

true
true

在上面的示例中,mergedPersistentEmpEntity是具有持久化的新实体。 因此,如果您想进行其他更改,请输入mergedPersistentEmpEntity实例。

本教程涵盖了 Hiberate 中的merge()refresh()方法。 请记住,可以问以下问题:merge()refresh()之间的差异,或merge()load()之间的差异等。准备好在面试问题中遇到这些差异。