jsp hibernate 資料儲存操作的原理

來源:互聯網
上載者:User

資料的儲存,更新和刪除:
1、Session.save()方法:
Session.save()方法用於實體物件的持久化儲存,也就是說當執行session.save()方法時會產生對應的insert SQL語句,完成資料的儲存。如下面的代碼:
User user=new User();
user.setName(“zx”);
Transaction tx=session.beginTransaction();
session.save(user);
tx.commit();
當執行到session.save()方法時,Hibernate並不會馬上產生insert SQL語句來進行資料的儲存,而是當稍後清理session的緩衝時才有可能執行insert SQL語句,那麼session.save()方法到底會執行哪些步驟呢?請看進行了如下總結:
一、 在session的內部緩衝中尋找儲存對象,如果找到了,則認為此資料已經儲存(曾經執行過insert操作),實體物件已經處於persistent狀態,直接返回。此時即使資料相比之前的狀態發生了變化,也將在事務提交時由髒資料檢查來判定是否需要執行update操作。
二、 如果實體物件實現了lifecycle介面,那麼將執行待儲存對象的onSave()方法。
三、 如果實體物件實現了Validatable介面,那麼將會執行相應的validate()方法。
四、 如果存在攔截器對象,那麼將會執行Interceptor.onSave()方法。
五、 構造insert SQL陳述式完成資料儲存。
六、 資料儲存成功後,設定實體物件的id為插入記錄的id。
七、 將儲存後的實體物件納入Hibernate的內部緩衝(一級緩衝)。注意Hibernate不會把儲存後的實體物件納入二級緩衝,因為剛剛儲存過的實體物件很可能在之後被修改,緩衝的頻繁更新以及帶來的同步問題代價,超出了緩衝該對象所帶來的收益。
八、 最後如果該對象有關聯對象,那麼將會遞迴處理該級聯對象。

1、 Session.update()方法:
前面我在實體物件狀態轉化部分曾經講過,session.update()方法能夠將一個處於游離狀態的對象,重新納入Hibernate的內部緩衝,變成持久化對象。如下面的代碼:
Configuration cfg = new Configuration();
SessionFactory sf=cfg. configure().buildSessionFactory();
Customer customer=new Customer(“zx”,27,images);//customer對象處於自由狀態
Session session=sf.openSession();

Transaction tx=session.beginTransaction();
session.save(customer);//儲存後customer對象處於持久化狀態
session.flush();//清空緩衝後customer對象處於游離狀態
tx.commit();
session.close();

Session session2=sf.openSession();
Transaction tx2=session2.beginTransaction();
session2.update(customer);//通過調用update()方法將游離狀態的customer對象,再次轉化成持久化狀態
session2.delete(customer);//調用delete()方法後,當清空緩衝時,會將customer對象移出緩衝,同時會在資料庫中產生delete事務,來刪除customer對象對應的資料記錄
tx.commit();
session.close();
那麼這個方法到底執行了哪些步驟呢?它會按照下面的步驟進行操作:
一、 首先會在緩衝中尋找需要更新的實體物件,如果找到就立刻返回,從這裡我們可以看出如果對一個已經處於persistent的實體物件執行update()方法,將不會產生任何作用。
二、 然後當提交事務進行緩衝清理時,將會通過髒資料檢查,確定變化的屬性,然後產生update SQL陳述式完成資料的更新。
這裡有一個問題我們要強調一下,那就是只要通過update()方法將一個游離對象與session相關聯,那麼不論這個游離的實體物件的屬性是否發生改變,都會執行update SQL語句。如下面的代碼:

Transaction tx=session.beginTransaction();
session.update(customer);
tx.commit();
session.close();
在這段代碼中並沒有修改customer對象的任何屬性值,但是也會執行一個update SQL語句,如果你希望在沒有改變實體物件屬性值的情況下不去執行update SQL語句,那麼你要開啟實體物件<class>元素的”select-before-update”屬性,將其設定為”true”,這個屬性預設為”false”。如下進行配置:
<class name=”com.neusoft.entity.Customer” table=”customer” select-before-update=”true”>
如果啟用了這個屬性配置,那麼在清理session緩衝之前,會首先執行類似如下的一條SQL語句:
Select * from customer where id='1';
查詢處所有的customer實體在資料庫中對應的屬性值,然後逐條與緩衝中屬性值進行比較,如果發生了改變,那麼將會產生update操作進行資料更新,如果沒有發生改變那麼將不會進行update操作。要跟據實際需求情況來決定是否開啟這個選項,如果實體物件的屬性不會經常發生改變,那麼就應該開啟這個選項,以免執行多餘的update操作。如果實體物件的屬性會經常發生改變,那麼就沒必要開啟這個選項,以免在執行update操作前再執行多餘的select語句。

註:(1)、當執行對一個游離實體物件執行session.update()操作時,如果在資料庫中不存在這個實體對應的紀錄,那麼這個操作將會拋出異常。
(2)、當執行session.update()方法將一個游離對象與session關聯時,如果此時在緩衝中已經存在了與該實體物件具有相同OID的持久化對象,那麼這個方法會拋出異常。如下面代碼:
Customer customer1=new Customer(“1”,“zx”,27,images);
Session session1=sf.openSession();
Transaction tx=session1.beginTransaction();
session.save(customer1);
session.flush();
tx.commit();
session1.close();

Session session2=sf.openSession();
Transaction tx2=session2.beginTransaction();
Customer othercustomer=(Customer)session2.load(Customer.class,”1”);
session2.update(customer1)
tx2.commit();
session2.close();
當再次將游離對象customer1與session2關聯時,此時因為load()操作,在緩衝已經載入了一個和customer1具有相同OID的othercustomer對象,此時由於Hibernate緩衝的對象緩衝機制不允許把OID相同的對象緩衝,所以會拋出異常。
2、 Session.saveOrUpdate():
這個方法包含了save()方法和update()方法的特點,如果傳入該方法的是一個游離對象,那麼這個方法就會執行update操作,如果傳入該方法的是一個臨時對象,那麼這個方法就會執行insert操作。這個方法幕後的工作原理如下:
a) 首先在緩衝尋找,如果找到待儲存的操作就直接返回。
b) 如果實體實現了攔截方法,那麼就執行isUnsaved()方法,判斷實體物件狀態。
c) 如果實體處於臨時狀態就執行save(),如果實體處於游離狀態那麼就執行update()。
這裡存在一個問題,那就是Hibernate是怎樣判斷一個實體是處於游離態還是臨時狀態的?如果實體滿足下面的一個條件,就認為這個實體處於臨時狀態。
.Java對象的OID值為null。
.如果Java對象具有version屬性(將在並發加鎖部分講解)且為null。
.如果實體的<id>設定了屬性unsaved-value,而且OID值與unsaved-value值相等。
.如果實體的version屬性設定了unsaved-value,並且version屬性的值與unsaved-value值相等。
.如果實體實現了Interceptor,而且Interceptor.isUnsaved()方法返回true。
滿足這些條件中的一個,這個實體就被認為是臨時對象。
3、 Session.delete():
delete()方法用於從資料庫中刪除一個或一批實體所對應的資料,如果傳入的對象是持久化對象,麼當清理緩衝時,就會執行delete操作。如果傳入的是游離對象,那麼首先會使該對象與session相關聯,然後當清理緩衝時,再執行delete操作。看如下代碼:
Session session=sessionFactory().openSession();
Transaction tx=session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class,”1”);
session.delete(customer);//計劃執行一條delete語句
tx.commit();//清理緩衝,執行一條delete語句
session.close();//關閉session,這時將會把customer對象從緩衝中刪除。
如果上面的代碼中的customer對象是一個游離對象,那麼當執行session.delete()方法時,會首先將游離的customer對象與session相關聯,然後再清理緩衝時,再執行delete操作。如果你想一次刪除多條資料,那麼可以採用一個重載的delete()方法:delete(“from Customer c where c.id>'8' ”);這個方法可以刪除合格所有資料。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.