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 方法