# Hiberate 合并和刷新实体

> 原文： [https://howtodoinjava.com/hibernate/merging-and-refreshing-hibernate-entities/](https://howtodoinjava.com/hibernate/merging-and-refreshing-hibernate-entities/)

在先前的教程中，我们了解了在 Hiberate 中使用`save()`或`saveOrUpdate()`方法[**保存实体**](//howtodoinjava.com/hibernate/save-and-saveorupdate-for-saving-hibernate-entities/ "Save() and saveOrUpdate() for Saving Hibernate Entities")的知识。 从中我们了解到，在大多数情况下，您甚至都不需要那些方法，因为 hibernate 自动管理[**持久实体**](//howtodoinjava.com/hibernate/hibernate-entity-persistence-lifecycle-states/ "Hibernate Entity / Persistence LifeCycle States")上的更新。 在大多数情况下，您只需要关心瞬态对象。 在本教程中，我将讨论有关 Hiberate 会话类中存在的`refresh()`和`merge()`方法的一些想法。

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

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

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

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

```

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

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

```java
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()`的作用完全相反，即，它使用来自分离实体的值更新数据库。 刷新方法是使用最新的数据库信息更新实体。 所以基本上，两者是完全相反的。

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

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

```

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

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

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

```java
EmployeeEntity mergedEmpEntity = session.merge(empEntity);

```

*   当`empEntity`传递给`merge()`方法时，它是分离的实体。
*   `merge()`方法将使用从`empEntity`获取的标识符信息搜索已加载的`EmployeeEntity`实例。 如果找到了这样的持久化实体，那么它将用于更新。 否则，将使用`empEntity`中存在的相同标识符信息将新的`EmployeeEntity`加载到会话中。
*   数据从`empEntity`复制到新发现/加载的实体。
*   由于新实体/发现实体是永久性的，因此从`empEntity`复制到该实体的所有数据都会自动保存到数据库中。
*   从`merge()`方法返回对该新实体的引用，并将其分配给`mergedEmpEntity`变量。
*   `empEntity`仍然是独立实体。

```java
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()`之间的差异等。准备好在[**面试问题**](//howtodoinjava.com/java-interview-questions/ "Java Interview Questions")中遇到这些差异。

**祝您学习愉快！**