save()、saveOrUpdate()、merge()的区别
一、Save()
save()方法能夠保存實(shí)體到數(shù)據(jù)庫。假如兩個(gè)實(shí)體之間有關(guān)系(例如employee表和address表有一對一關(guān)系),如果在沒有事務(wù)的情況下調(diào)用這個(gè)方法保存employee這個(gè)實(shí)體,除非調(diào)用flush()這個(gè)方法,否則僅僅employee實(shí)體會(huì)被保存。?
二、SaveOrUpdate()
?
saveOrUpdate()方法會(huì)執(zhí)行插入或者更新操作。如果該對象在數(shù)據(jù)庫中已經(jīng)存在則更新,不存在則插入。
?
也可以在沒有事務(wù)的情況下執(zhí)行,但是如果沒有手動(dòng)調(diào)用flush()方法會(huì)面臨關(guān)聯(lián)對象不被保存的問題
?
save()方法與saveOrUpdate()方法最大的不同點(diǎn)在于:saveOrUpdate()方法會(huì)將實(shí)體對象添加到持久化上下文中,該實(shí)體的后續(xù)改變會(huì)被跟蹤。
例子:
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;} }執(zhí)行代碼,輸出結(jié)果:
*********************************************** 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 ***********************************************注意:如果沒有事務(wù),僅僅是employee實(shí)體被保存到數(shù)據(jù)庫,而address的信息丟失了。
在事務(wù)tx4中的幾行代碼employee實(shí)體的name屬性先被修改為“Updated Test Name”,之后又被賦值為原來的值“Kumar”,因此employee這個(gè)實(shí)體在事務(wù)提交之前并沒有改變,所以并沒有update操作。
三、Merge()
如果某對象處于游離態(tài),游離態(tài)是指該對象的id值為空。hibernate判斷一個(gè)對象在數(shù)據(jù)庫中是否存在不是看對象的其他信息,而是判斷該id在數(shù)據(jù)庫中是不是存在。如果id為空,那自然是不存在,所以當(dāng)我們調(diào)用merge方法的時(shí)候,就會(huì)直接執(zhí)行插入操作。這一點(diǎn)有點(diǎn)像saveorupdate()方法。
?
Object merge(Object object)throws HibernateException?
The semantics of this method are defined by JSR-220.
?
首先從參數(shù)說明來看,merge的參數(shù)應(yīng)該是一個(gè)處于托管狀態(tài)的實(shí)例對象,而返回值則是一個(gè)持久化對象。但是這里的參數(shù)并不是一定要是托管狀態(tài)的對象,它還可以是瞬態(tài)和持久化的實(shí)例對象。正因如此,才使merge方法變得復(fù)雜化。
?
經(jīng)代碼檢驗(yàn)從merge方法產(chǎn)生的效果來看,它和saveOrUpdate方法相似,因此雖然上面提到是因?yàn)閰?shù)狀態(tài)的不同造成復(fù)雜化,但是這里我并不打算分參數(shù)的不同狀態(tài)來理解merge,而是根據(jù)參數(shù)有無id或id是否已經(jīng)存在來理解merge。個(gè)人認(rèn)為這樣更容易理解,而且從執(zhí)行他們兩個(gè)方法而產(chǎn)生的sql語句來看是一樣的。
?
1. 參數(shù)實(shí)例對象沒有提供id或提供的id在數(shù)據(jù)庫中不存在:這時(shí)merge將執(zhí)行插入操作,產(chǎn)生的sql語句如下,???????
?
????????? Hibernate: select max(uid) from user?????
?
????????? Hibernate: insert into hibernate1.user (name, age, uid) values (?, ?, ?)
?
2. 參數(shù)實(shí)例對象的id在數(shù)據(jù)庫中已經(jīng)存在,此時(shí)又有兩種情況:
?
(1)如果對象有改動(dòng),則執(zhí)行更新操作,產(chǎn)生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)如果對象為改動(dòng),則執(zhí)行查詢操作,產(chǎn)生的語句有,
?
???????? 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的返回值都是一個(gè)持久化的實(shí)例對象,但對于參數(shù)而言不會(huì)改變它的狀態(tài)。
?
雖然從功能上merge方法與saveOrUpdate類似,但他們?nèi)杂袇^(qū)別。現(xiàn)在有這樣一種情況:我們先通過session的get方法得到一個(gè)對象u,然后關(guān)掉session,再打開一個(gè)session并執(zhí)行saveOrUpdate(u)。此時(shí)我們可以看到拋出異常:Exception in thread "main" org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session,即在session緩存中不允許有兩個(gè)id相同的對象。不過若使用merge方法則不會(huì)異常,其實(shí)從merge的中文意思(合并)我們就可以理解了。
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/WJ-163/p/5827018.html
總結(jié)
以上是生活随笔為你收集整理的save()、saveOrUpdate()、merge()的区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转载】fullpage.js学习
- 下一篇: IIS 部署asp.net Core程序