原文: https://howtodoinjava.com/hibernate/merging-and-refreshing-hibernate-entities/

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

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

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

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

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

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

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

  1. public class RefreshEntityExample
  2. {
  3. public static void main(String[] args)
  4. {
  5. Session sessionOne = HibernateUtil.getSessionFactory().openSession();
  6. sessionOne.beginTransaction();
  7. //Create new Employee object
  8. EmployeeEntity emp = new EmployeeEntity();
  9. emp.setEmployeeId(1);
  10. emp.setFirstName("Lokesh");
  11. emp.setLastName("Gupta");
  12. //Save employee
  13. sessionOne.save(emp);
  14. sessionOne.getTransaction().commit();
  15. sessionOne.close();
  16. //Verify employee's firstname
  17. System.out.println(verifyEmployeeFirstName(1, "Lokesh"));
  18. Session sessionTwo = HibernateUtil.getSessionFactory().openSession();
  19. sessionTwo.beginTransaction();
  20. //This
  21. emp.setFirstName("Vikas");
  22. sessionTwo.refresh(emp);
  23. sessionTwo.getTransaction().commit();
  24. sessionTwo.close();
  25. System.out.println(emp.getFirstName().equals("Lokesh"));
  26. HibernateUtil.shutdown();
  27. }
  28. private static boolean verifyEmployeeFirstName(Integer employeeId, String firstName){
  29. Session session = HibernateUtil.getSessionFactory().openSession();
  30. EmployeeEntity employee = (EmployeeEntity) session.load(EmployeeEntity.class, employeeId);
  31. //Verify first name
  32. boolean result = firstName.equals(employee.getFirstName());
  33. session.close();
  34. //Return verification result
  35. return result;
  36. }
  37. }
  38. Output:
  39. true
  40. true

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

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

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

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

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

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

  1. Object merge(Object object)
  2. Object merge(String entityName, Object object)

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

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

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

  1. EmployeeEntity mergedEmpEntity = session.merge(empEntity);
  • empEntity传递给merge()方法时,它是分离的实体。
  • merge()方法将使用从empEntity获取的标识符信息搜索已加载的EmployeeEntity实例。 如果找到了这样的持久化实体,那么它将用于更新。 否则,将使用empEntity中存在的相同标识符信息将新的EmployeeEntity加载到会话中。
  • 数据从empEntity复制到新发现/加载的实体。
  • 由于新实体/发现实体是永久性的,因此从empEntity复制到该实体的所有数据都会自动保存到数据库中。
  • merge()方法返回对该新实体的引用,并将其分配给mergedEmpEntity变量。
  • empEntity仍然是独立实体。
  1. public class MergeEntityExample
  2. {
  3. public static void main(String[] args)
  4. {
  5. Session sessionOne = HibernateUtil.getSessionFactory().openSession();
  6. sessionOne.beginTransaction();
  7. //Create new Employee object
  8. EmployeeEntity emp = new EmployeeEntity();
  9. emp.setEmployeeId(1);
  10. emp.setFirstName("Lokesh");
  11. emp.setLastName("Gupta");
  12. //Save employee
  13. sessionOne.save(emp);
  14. sessionOne.getTransaction().commit();
  15. sessionOne.close();
  16. //Verify employee's firstname
  17. System.out.println(verifyEmployeeFirstName(1, "Lokesh"));
  18. Session sessionTwo = HibernateUtil.getSessionFactory().openSession();
  19. sessionTwo.beginTransaction();
  20. //Set new first name
  21. emp.setFirstName("Vikas");
  22. //Merge the emp object using merge() method
  23. EmployeeEntity mergedPersistentEmpEntity = (EmployeeEntity) sessionTwo.merge(emp);
  24. sessionTwo.getTransaction().commit();
  25. sessionTwo.close();
  26. //Verify employee's firstname again in database
  27. System.out.println(verifyEmployeeFirstName(1, "Vikas"));
  28. HibernateUtil.shutdown();
  29. }
  30. private static boolean verifyEmployeeFirstName(Integer employeeId, String firstName){
  31. Session session = HibernateUtil.getSessionFactory().openSession();
  32. EmployeeEntity employee = (EmployeeEntity) session.load(EmployeeEntity.class, employeeId);
  33. //Verify first name
  34. boolean result = firstName.equals(employee.getFirstName());
  35. session.close();
  36. //Return verification result
  37. return result;
  38. }
  39. }
  40. Output:
  41. true
  42. true

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

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

祝您学习愉快!