原文: 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()方法之一来刷新持久对象的实例,如下所示:
public void refresh(Object object) throws HibernateExceptionpublic 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 objectEmployeeEntity emp = new EmployeeEntity();emp.setEmployeeId(1);emp.setFirstName("Lokesh");emp.setLastName("Gupta");//Save employeesessionOne.save(emp);sessionOne.getTransaction().commit();sessionOne.close();//Verify employee's firstnameSystem.out.println(verifyEmployeeFirstName(1, "Lokesh"));Session sessionTwo = HibernateUtil.getSessionFactory().openSession();sessionTwo.beginTransaction();//Thisemp.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 nameboolean result = firstName.equals(employee.getFirstName());session.close();//Return verification resultreturn result;}}Output:truetrue
查看突出显示的线条上方。
- 第 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 objectEmployeeEntity emp = new EmployeeEntity();emp.setEmployeeId(1);emp.setFirstName("Lokesh");emp.setLastName("Gupta");//Save employeesessionOne.save(emp);sessionOne.getTransaction().commit();sessionOne.close();//Verify employee's firstnameSystem.out.println(verifyEmployeeFirstName(1, "Lokesh"));Session sessionTwo = HibernateUtil.getSessionFactory().openSession();sessionTwo.beginTransaction();//Set new first nameemp.setFirstName("Vikas");//Merge the emp object using merge() methodEmployeeEntity mergedPersistentEmpEntity = (EmployeeEntity) sessionTwo.merge(emp);sessionTwo.getTransaction().commit();sessionTwo.close();//Verify employee's firstname again in databaseSystem.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 nameboolean result = firstName.equals(employee.getFirstName());session.close();//Return verification resultreturn result;}}Output:truetrue
在上面的示例中,mergedPersistentEmpEntity是具有持久化的新实体。 因此,如果您想进行其他更改,请输入mergedPersistentEmpEntity实例。
本教程涵盖了 Hiberate 中的merge()和refresh()方法。 请记住,可以问以下问题:merge()和refresh()之间的差异,或merge()和load()之间的差异等。准备好在面试问题中遇到这些差异。
祝您学习愉快!
