一切的一切都要從資料的插入開始,沒有資料的插入就沒有資料來進行更新、刪除和修改。在Hibernate中使用最頻繁的用來插入資料的方法就是save()方法了。在Hibernate的官方API中對save方法的注釋很簡單:將指定的臨時對象持久化,並首先指定一個標識符,也就是我們所說的OID,但是如果OID的建置原則是assigned的時候除外。
注釋雖然很簡單,但是卻向我們披露了足夠的資訊。我們從輸入、操作、輸出對它進行分析。
1.輸入:一個處於臨時狀態的對象。這並不是說我們不能使用持久化對象和游離對象做參數,只是說這樣操作不合規範。就像男人穿裙子一樣,不是說你不能穿,只是這樣不合常理而已。
2.操作:首先根據指定的OID建置原則給臨時對象產生一個OID,一般來說此時臨時對象的OID是NULL,除非你使用了assign策略或者人為的指定了一個OID,但是事實證明這時沒有用的;接著把這個對象置入緩衝中,使它成為持久化對象;最後,計劃一個insert語句,注意,只是計劃,並沒有執行,只有當Session清理緩衝時才執行sql語句。
3.輸出:一個持久化對象和一條sql語句,這個說法不是很準確,這樣說只是為了便於理解而已。
就我的理解,save()方法就像魔獸中英雄在外面練級的時候,把野怪身上掉的寶物撿起來放在身上一樣。
前面我們說人為指定OID是沒有用的,可以通過如下的程式碼片段來進行驗證:
Customer customer=new Customer();
customer.setId(3L);
session.save(customer);
System.out.println(customer.getId());
結果表明,程式最後輸出的ID是根據標識符產生器產生的。另外還要注意的一點就是,當對象處於持久化狀態時,不能再隨意修改它的OID,否則Session在清理緩衝時會拋出異常,如:
Customer customer=new Customer();
session.save(customer);
customer.setId(3L);
tx.commit();
此時程式拋出如下異常:org.hibernate.HibernateException: identifier of an instance of cn.edu.hust.cm.mypack.Customer was altered from 7 to 3
我還做了如下一個實驗,程式碼片段如下:
Customer customer=new Customer();
session.save(customer);
session.save(customer);
tx.commit();
第一次調用save()方法時customer處於臨時狀態,而第二次調用save()方法是時它已經處於持久化狀態了,事實證明第二次的save操作完全是多餘的,Hibernate並沒有為它再計劃一個insert語句。