標籤:style c class blog code java
一、Hibernate緩衝簡介:
Session介面是Hibernate嚮應用程式提供的操縱資料介面的最主要介面,它提供了基本的儲存、更新、刪除和載入Java對象的方法。
Session具有一個緩衝,位於緩衝中的對象稱為持久化對象,Session能夠在某些時間點來同步更新資料庫,這一過程即為清理緩衝。
Hibernate把對象分為4種狀態:持久化狀態、臨時狀態、游離狀態和刪除狀態。
二、Session的緩衝:
Session的緩衝由一系列Java集合構成的。
1、Session緩衝的作用:
A、減少訪問資料庫的頻率。
B、當緩衝中的持久化對象之間存在迴圈關聯關係時,Session保證不會出現訪問對象圖的死迴圈,以及由死迴圈引起的JVM堆疊溢位異常。
C、保證資料庫中的相關記錄和緩衝中的相應對象儲存同步。Session通過在清理緩衝時進行髒檢查來同步。
2、髒檢查及清理緩衝的機制:
當一個對象被加入到Session緩衝中時,Session會為該對象的實值型別的屬性複製一份快照。在清理緩衝進行髒檢查時,就是拿對象的當前屬性和它的快照進行對比,據此判斷是否發生了變化。
另外,當對象屬性發生變化時,Session並不會立即清理緩衝和執行相關的SQL操作,而是在特定的時間才清理緩衝。這樣的好處就是Session能夠把幾條相關的SQL語句合并為一條SQL,從而減少訪問資料庫的次數。
Session清理緩衝時,按照以下順序執行SQL語句(瞭解):
?
| 1 2 3 4 5 6 |
A、按照session.save()方法先後順序,執行所有對實體進行插入的insert語句。 B、執行所有對實體進行更新的update語句。 C、執行所有對集合進行刪除的delete語句。 D、執行所有對集合元素進行刪除、更新或者插入的SQL語句。 E、執行所有對集合進行插入的insert語句。 F、按照應用程式調用session.delete()方法的先後順序,執行所有對實體進行刪除的delete語句。 |
Session會在以下時間點清理緩衝:
?
| 1 2 3 |
A、當應用程式調用org.hibernate.Transaction分commit()方法時,先清理緩衝,再提交事務。 B、當應用程式執行一些查詢操作時,如果緩衝中的持久化對象屬性發生了變化,就會先清理緩衝。 C、當應用程式顯式調用Session的flush()方法的時候。 |
例外情況:如果對象使用native產生器來產生OID,name當調用Session的 save()方法儲存對象時,會立即執行insert語句。
也可以通過Session.setFlushMode()方法來顯式的設定清理緩衝的時間點。
多數情況下應用程式不需要顯式的調用flush()方法,以下常見除外:
A、插入、刪除或更新某個持久化對象會引發資料庫中觸發器的時候。
B、在應用程式中混合使用Hibernate API和JDBC API的時候。
C、JDBC驅動程式不健壯,導致Hibernate在自動清理緩衝模式下無法正常工作的時候。
三、Java對象在Hibernate持久化層的狀態:
1、狀態原因:
A、臨時狀態(transient):剛用new語句建立,還沒有被持久化,並且不處於Session的緩衝中。
B、持久化對象(persistent):已經被持久化,並且加入到Session緩衝中。
C、刪除狀態(delete):不再處於Session的緩衝中,並且Session已經計劃將其從資料庫中刪除。
D、游離狀態(detached):已經被持久化,但是不再處於Session的緩衝中。
2、狀態轉換圖:
3、臨時對象的特徵:
A、在使用代理主鍵的情況下,OID通常為NULL。
B、不處於Session的緩衝中,不被任何一個Session執行個體關聯。
C、在資料庫中沒有對應的記錄。
四、持久化對象的特徵:
1、OID不為null。
2、位於一個Session執行個體的緩衝中。持久化對象總是被一個Session執行個體關聯。
3、持久化對象和資料庫中的相關記錄對應。
4、Session在清理緩衝時,會根據持久化對象的屬性變化,來同步更新資料庫。
五、被刪除對象的特徵:
1、OID不為null。
2、從一個Session執行個體的緩衝中刪除。
3、被刪除對象和資料庫中的相關記錄對應。
4、Session已經計劃將其從資料庫中刪除。
5、Session在清理緩衝時,會執行SQL delete語句,刪除資料庫中的相應記錄。
6、一般情況下,應用程式不應該再使用被刪除的對象。
六、游離對象的特徵:
1、OID不為null。
2、不再位於Session的緩衝中。
3、游離對象是由持久化對象轉變過來的,因此在資料庫中可能還存在與它相對應的記錄。
游離對象和臨時對象的相同之處:兩者都不被Session關聯,因此不會保證它們的屬性變化與資料庫儲存同步。
游離對象和臨時對象的不同之處:游離對象是由持久化對象轉變過來的,因此資料庫中可能存在對應的記錄,而臨時對象在資料庫中沒有與之對應的記錄。
游離對象與被刪除對象的相同之處:兩者都不位於Session的緩衝中,並且資料庫中都可能存在對應的記錄。
游離對象與被刪除對象的不同之處:游離對象與Session完全脫離關係,而對於被刪除對象,Session會計劃將其從資料庫中刪除,在清理緩衝時會執行刪除操作。
七、Session介面的詳細用法:
1、Session的save()和persist()方法:
save()方法使一個臨時對象轉變為持久化對象。注意應該禁止應用程式修改OID。
persist()方法和save()方法類似,區別在於該方法是在Hibernate3版本中財出現的。且如果在事務邊界以外調用persist()方法時,不會執行SQL insert語句。
2、Session的load()和get()方法:
這兩個方法都能根據給定的OID從資料庫中載入一個持久化對象。
區別在於:
A、當資料庫中不存在與OID對應的記錄時,load()方法拋出OjbectNotFoundException,而get()方法返回null。
B、兩者採用不同的檢索策略(檢索策略後續描述)。load()方法根據<class>元素的lazy屬性決定是否進行懶載入,而get()方法會忽略lazy屬性,採用立即檢索策略。
使用情境:
A、如果載入一個對象的目的是訪問它的各個屬性,可以用get()方法。
B、如果載入一個對象時為了刪除它,或者威力建立和別的對象的關聯,可以用load()方法。
3、Session的update()方法:
update()方法使一個游離對象轉變為持久化對象,並計劃執行一條update語句。
如果希望Session僅在修改了對象的屬性時才執行update語句,可以把<class>元素的select-before-update設定為true。
當update()方法關聯一個游離對象時,如果在Session緩衝中已經存在相同OID的持久化對象,會拋出異常。
4、Session的saveOrUpdate()方法:
saveOrUpdate()方法同時包含了save()和update()方法。如果傳入的參數是臨時對象,調用save()方法;如果傳入的參數是游離對象,就調用update()方法;如果傳入的是持久化對象,就直接返回。
滿足下列任何一個條件,Hibernate就會認為該對象時臨時對象:
A、Java對象的OID為null。
B、Java對象具有version版本控制屬性並且取值為null(不明白)。
C、在對應檔中為<id>元素設定了unsaved-value屬性,並且Java對象的OID與這個屬性值匹配。
D、在設定檔中為version版本控制屬性設定了unsaved-value屬性,並且Java對象的version版本控制屬性的取值與該屬性值匹配。
E、為Hibernate的Interceptor提供了自訂的實現,並且Interceptor實作類別的isUnsaved()方法返回Boolean.TRUE。
5、Session的merger()方法:
merge()方法能夠把一個游離對象的屬性複製到一個持久化對象中。
6、Session的delete()方法:
delete()方法用於從資料庫中刪除一個Java對象。既可以刪除持久化對象,也可以刪除游離對象。
7、Session的replicate()對象:
該方法能夠把一個資料庫中的對象複製到另一個資料庫中。(暫不關注)
八、級聯操作對象圖:
1、cascade屬性工作表:
(聲明:該文所有內容均來自《精通Hibernate:Java對象持久化技術詳解》[孫衛琴 電子工業出版社] 一書。該文的目的僅僅作為學習筆記。若需要轉載,請註明原書相關資訊。)