merge() 方法的细微差别

如果你想使用 Hibernate 来改变一个已经存储在数据库中的对象,那么也有几种方法可以做到这一点。

第一个是merge()方法,它根据传递的对象更新数据库中的信息。这将调用 SQL UPDATE 查询。例子:

User user = new User();
user.setName("Kolyan");
session.save(user);

session.evict(user);     // detach the object from the session
user.setName("Masha");

User user2 = (User) session.merge(user);

这里有几个重要的细微差别。

首先,merge()方法返回结果,即更新后的对象。该对象具有 Persist 状态并附加到会话对象。传递给merge()方法的对象不会改变。

user 和 user2 之间似乎没有区别,但事实并非如此。您可以将一个 POJO 对象传递给merge()方法,结果,该方法可以返回一个代理(取决于 Hibernate 设置)。所以请记住merge()方法不会更改传递的对象。

其次,如果传递给merge()的对象具有 Transient 状态(并且它没有 ID),那么将在数据库中为其创建一个单独的行。换句话说,将执行persist()命令。

第三,如果一个已经附加到会话的对象(具有 Persist 状态)被传递给merge()方法,那么什么也不会发生——该方法将简单地返回同一个对象。为什么?这一切都是因为当事务被提交时,数据无论如何都会被写入数据库:

User user = new User();
user.setName("Kolyan");
session.save(user);

user.setName("Masha"); //change the object attached to the session

session.close();  //all changed objects will be written to the database

每次更改后都不需要保存对象。如果这个对象处于 Persist 状态,那么 Hibernate 会自己做所有事情。如果更改“附加到基础”的对象,则其所有更改都将写入基础。

update() 方法的细微差别

Hibernate 也有一个update()方法,它和save()方法一样,是从以前的版本继承而来的。使用此方法,您只能更新已保存对象的数据。这将调用 SQL UPDATE 查询。例子:

User user = new User();
user.setName("Kolyan");
session.save(user);

session.evict(user);     // detach the object from the session
user.setName("Masha");

session.update(user);

此方法不返回任何内容,也不更改现有对象。

如果您在一个新对象上调用此方法,则会抛出一个异常:

User user = new User();
user.setName("Kolyan");
session.update(user);   //an exception will be thrown here

saveOrUpdate() 方法

在JPA出现之前,persist()方法的功能是由saveOrUpdate()方法完成的。他的任务是更新数据库中现有对象的信息,如果没有,则创建它。它几乎总是用来代替save()update()方法。

与update()方法不同,它可以更改传递给它的对象。例如,将其设置为保存到数据库时分配的 ID。例子:

User user = new User();
user.setName("Kolyan");
session.saveOrUpdate(user);   //object will be written to the database

怎么运行的:

  • 如果传递的对象有 ID,则调用 UPDATE SQL 方法
  • 如果未设置传递对象的 ID,则调用 INSERT SQL 方法