標籤:c style class blog java a
站在持久化的角度, Hibernate 把對象分為 4 種狀態: 持久化狀態, 臨時狀態, 游離狀態, 刪除狀態. Session 的特定方法能使對象從一個狀態轉換到另一個狀態.
持久化對象的狀態臨時對象(Transient):
–在使用代理主鍵的情況下, OID 通常為null–不處於 Session的緩衝中–在資料庫中沒有對應的記錄
持久化對象(也叫”託管”)(Persist):
–OID 不為null–位於 Session緩衝中–若在資料庫中已經有和其對應的記錄,持久化對象和資料庫中的相關記錄對應–Session 在 flush緩衝時,會根據持久化對象的屬性變化,來同步更新資料庫–在同一個 Session執行個體的緩衝中,資料庫表中的每條記錄只對應唯一的持久化對象
刪除對象(Removed)
–在資料庫中沒有和其 OID 對應的記錄–不再處於 Session緩衝中–一般情況下, 應用程式不該再使用被刪除的對象
游離對象(也叫”脫管”) (Detached):
OID 不為 null
不再處於 Session 緩衝中
一般情況需下, 游離對象是由持久化對象轉變過來的, 因此在資料庫中可能還存在與它對應的記錄
對象的狀態轉換圖
save()與persist()
- Session 的 save() 方法使一個臨時對象轉變為持久化對象
- Session 的 save() 方法完成以下操作:
–把 News對象加入到Session緩衝中,使它進入持久化狀態–選用對應檔指定的標識符產生器, 為持久化對象分配唯一的OID.在使用代理主鍵的情況下, setId()方法為News對象設定OID是無效的.資料庫會自動重新分配id–計劃執行一條 insert 語句:在 flush緩衝的時候
- Hibernate 通過持久化對象的 OID 來維持它和資料庫相關記錄的對應關係. 當 News 對象處於持久化狀態時,不允許程式隨意修改它的 ID
- persist() 和 save() 區別(persist()也會執行insert操作):
–當對一個 OID 不為Null的對象執行save()方法時,會把該對象以一個新的oid儲存到資料庫中; 但執行 persist()方法時會拋出一個異常.(在調用persist方法之前,若對象已經有id了,則不會執行insert,,而拋出一個異常)
get()與load()
- 都可以根據跟定的 OID 從資料庫中載入一個持久化對象
- 執行load方法,若不使用該對象,則不會立即執行查詢操作,而返回一個代理對象
- 區別:
–當資料庫中不存在與OID對應的記錄時,且session也沒有被關閉,load()若不使用該對象沒問題,若需要初始化了,會拋出 ObjectNotFoundException異常,而get()方法返回null–兩者採用不同的延遲檢索策略:load方法支援消極式載入策略。而get 不支援。–load()可能會拋出LazyInitializationException 異常:在需要初始化代理對象之前已經關閉了session
update()
- 若更新一個持久化對象,不需要顯示地調用update方法,因為在調用Transaction的commit()方法時,會先執行session的flush方法
- Session 的 update() 方法使一個游離對象轉變為持久化對象, 並且計劃執行一條 update 語句.
- 注意:
1.無論要更新的游離對象和資料庫的記錄是否一致,都會發送update語句 如何能讓update方法不盲目的觸發update語句呢?若希望 Session 僅當修改了 News 對象的屬性時, 才執行 update() 語句, 可以把對應檔中 <class> 元素的 select-before-update 設為 true. 該屬性的預設值為 false,但通常不需要設定該設定該屬性(在update的情況下需要多發一條select語句)2.當 update() 方法關聯一個游離對象時, 如果在資料庫中不存在相應的記錄, 也會拋出異常. 3.當 update() 方法關聯一個游離對象時, 如果在 Session 的緩衝中已經存在相同 OID 的持久化對象, 會拋出異常。因為在session緩衝中不能有兩個oid相同的對象。
saveOrUpdate()
- Session 的 saveOrUpdate() 方法同時包含了 save() 與 update() 方法的功能
- 判定對象為臨時對象的標準
–Java 對象的 OID 為 null–對應檔中為<id>設定了unsaved-value 屬性,並且Java對象的OID取值與這個unsaved-value屬性值匹配
- 注意
1.若OID不為null,但資料表中還沒有和其對應的記錄,會拋出一個異常2.瞭解:OID值等於id的unsaved-value屬性的對象也被認為是一個游離對象
merge()
delete()
- 執行刪除操作,只要OID和資料表中一條記錄對應,就會準備執行delete操作,若OID在資料表中沒有對應的記錄,則拋出異常
- Session 的 delete() 方法既可以刪除一個游離對象, 也可以刪除一個持久化對象
- Session的delete()方法處理過程–計劃執行一條delete語句(提交之前該對象還是具有OID的,還是可以使用該對象)–提交之後把對象從Session緩衝中刪除,該對象進入刪除狀態.
- Hibernate的cfg.xml設定檔中有一個hibernate.use_identifier_rollback屬性,其預設值為false,若把它設為true,將改變delete()方法的運行行為:delete() 方法會把持久化對象或游離對象的 OID設定為null,使它們變為臨時對象
evict()
通過 Hibernate 調用預存程序Work 介面: 直接通過 JDBC API 來訪問資料庫的操作
Session 的 doWork(Work) 方法用於執行 Work 對象指定的操作, 即調用 Work 對象的 execute() 方法. Session 會把當前使用的資料庫連接傳遞給 execute() 方法.
Hibernate 與觸發器協同工作Hibernate 與資料庫中的觸發器協同工作時, 會造成兩類問題
–觸發器使Session的緩衝中的持久化對象與資料庫中對應的資料不一致:觸發器運行在資料庫中,它執行的操作對Session是透明的–Session的update()方法盲目地激發觸發器:無論游離對象的屬性是否發生變化,都會執行update語句,而update語句會激發資料庫中相應的觸發器
解決方案:
–在執行完Session的相關操作後,立即調用Session的flush()和refresh()方法,迫使Session的緩衝與資料庫同步(refresh()方法重新從資料庫中載入對象)
-在對應檔的的 <class> 元素中設定 select-before-update 屬性: 當 Session 的 update 或 saveOrUpdate() 方法更新一個游離對象時, 會先執行 Select 語句, 獲得當前游離對象在資料庫中的最新資料, 只有在不一致的情況下才會執行 update 語句