save()、saveOrUpdate()、merge()的区别
一、Save()
save()方法能夠保存實體到數據庫。假如兩個實體之間有關系(例如employee表和address表有一對一關系),如果在沒有事務的情況下調用這個方法保存employee這個實體,除非調用flush()這個方法,否則僅僅employee實體會被保存。?
二、SaveOrUpdate()
?
saveOrUpdate()方法會執行插入或者更新操作。如果該對象在數據庫中已經存在則更新,不存在則插入。
?
也可以在沒有事務的情況下執行,但是如果沒有手動調用flush()方法會面臨關聯對象不被保存的問題
?
save()方法與saveOrUpdate()方法最大的不同點在于:saveOrUpdate()方法會將實體對象添加到持久化上下文中,該實體的后續改變會被跟蹤。
例子:
package nd.esp.com.hibernate.example;import nd.esp.com.hibernate.model.Address; import nd.esp.com.hibernate.model.Employee; import nd.esp.com.hibernate.utils.HibernateUtil;import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction;public class HibernateSaveOrUpdateExample {public static void main(String[] args) {// Prep WorkSessionFactory sessionFactory = HibernateUtil.getSessionFactory();System.out.println("***********************************************");// saveOrUpdate example - without transactionSession session5 = sessionFactory.openSession();Employee emp5 = getTestEmployee();session5.saveOrUpdate(emp5);System.out.println("***********************************************");// saveOrUpdate example - with transactionSession session3 = sessionFactory.openSession();Transaction tx3 = session3.beginTransaction();Employee emp3 = getTestEmployee();session3.saveOrUpdate(emp3);emp3.setName("Kumar"); // will be saved into DBSystem.out.println("9. Before committing saveOrUpdate transaction. Id=" + emp3.getId());tx3.commit();System.out.println("10. After committing saveOrUpdate transaction");System.out.println("***********************************************");Transaction tx4 = session3.beginTransaction();emp3.setName("Updated Test Name"); // Name changedemp3.getAddress().setCity("Updated City");session3.saveOrUpdate(emp3);emp3.setName("Kumar"); // again changed to previous value, so no Employee updateSystem.out.println("11. Before committing saveOrUpdate transaction. Id=" + emp3.getId());tx4.commit();System.out.println("12. After committing saveOrUpdate transaction");System.out.println("***********************************************");// Close resources sessionFactory.close();}public static Employee getTestEmployee() {Employee emp = new Employee();Address add = new Address();emp.setName("Test Emp");add.setCity("Test City");emp.setAddress(add);add.setEmployee(emp);return emp;} }執行代碼,輸出結果:
*********************************************** Hibernate: insert into EMPLOYEE (emp_name) values (?) *********************************************** Hibernate: insert into EMPLOYEE (emp_name) values (?) 9. Before committing saveOrUpdate transaction. Id=21 Hibernate: insert into ADDRESS (city, emp_id) values (?, ?) Hibernate: update EMPLOYEE set emp_name=? where emp_id=? 10. After committing saveOrUpdate transaction *********************************************** 11. Before committing saveOrUpdate transaction. Id=21 Hibernate: update ADDRESS set city=? where emp_id=? 12. After committing saveOrUpdate transaction ***********************************************注意:如果沒有事務,僅僅是employee實體被保存到數據庫,而address的信息丟失了。
在事務tx4中的幾行代碼employee實體的name屬性先被修改為“Updated Test Name”,之后又被賦值為原來的值“Kumar”,因此employee這個實體在事務提交之前并沒有改變,所以并沒有update操作。
三、Merge()
如果某對象處于游離態,游離態是指該對象的id值為空。hibernate判斷一個對象在數據庫中是否存在不是看對象的其他信息,而是判斷該id在數據庫中是不是存在。如果id為空,那自然是不存在,所以當我們調用merge方法的時候,就會直接執行插入操作。這一點有點像saveorupdate()方法。
?
Object merge(Object object)throws HibernateException?
The semantics of this method are defined by JSR-220.
?
首先從參數說明來看,merge的參數應該是一個處于托管狀態的實例對象,而返回值則是一個持久化對象。但是這里的參數并不是一定要是托管狀態的對象,它還可以是瞬態和持久化的實例對象。正因如此,才使merge方法變得復雜化。
?
經代碼檢驗從merge方法產生的效果來看,它和saveOrUpdate方法相似,因此雖然上面提到是因為參數狀態的不同造成復雜化,但是這里我并不打算分參數的不同狀態來理解merge,而是根據參數有無id或id是否已經存在來理解merge。個人認為這樣更容易理解,而且從執行他們兩個方法而產生的sql語句來看是一樣的。
?
1. 參數實例對象沒有提供id或提供的id在數據庫中不存在:這時merge將執行插入操作,產生的sql語句如下,???????
?
????????? Hibernate: select max(uid) from user?????
?
????????? Hibernate: insert into hibernate1.user (name, age, uid) values (?, ?, ?)
?
2. 參數實例對象的id在數據庫中已經存在,此時又有兩種情況:
?
(1)如果對象有改動,則執行更新操作,產生sql語句有,
?
???????? Hibernate: select user0_.uid as uid0_0_, user0_.name as name0_0_, user0_.age as age0_0_ from hibernate1.user user0_ where user0_.uid=??
???????? Hibernate: update hibernate1.user set name=?, age=? where uid=?
?
(2)如果對象為改動,則執行查詢操作,產生的語句有,
?
???????? Hibernate: select user0_.uid as uid0_0_, user0_.name as name0_0_, user0_.age as age0_0_ from hibernate1.user user0_ where user0_.uid=?
?
不管哪種情況,merge的返回值都是一個持久化的實例對象,但對于參數而言不會改變它的狀態。
?
雖然從功能上merge方法與saveOrUpdate類似,但他們仍有區別?,F在有這樣一種情況:我們先通過session的get方法得到一個對象u,然后關掉session,再打開一個session并執行saveOrUpdate(u)。此時我們可以看到拋出異常:Exception in thread "main" org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session,即在session緩存中不允許有兩個id相同的對象。不過若使用merge方法則不會異常,其實從merge的中文意思(合并)我們就可以理解了。
?
?
?
轉載于:https://www.cnblogs.com/WJ-163/p/5827018.html
總結
以上是生活随笔為你收集整理的save()、saveOrUpdate()、merge()的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转载】fullpage.js学习
- 下一篇: 分享一个免费短信猫OCX源码