程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 在Hibernate中正確實現關聯關系中的級聯操作(cascading)

在Hibernate中正確實現關聯關系中的級聯操作(cascading)

編輯:關於JAVA

關系數據庫系統本身就比較復雜,加上Hibernate的O/R映射層,復雜度加重了,很容易出現問題,本人將最近遇到的問題和解決方法做一個總結,整理在下面的一系列文章中

正確理解Hibernate的聚合類型(collection)的使用

在Hibernate中正確實現關聯關系中的級聯操作(cascading)

在Hibernate框架中編寫持久對象類實現外鍵關聯的幾點注意事項

本文是第二篇,講解在one-to-many(一對多)和many-to-one(多對一)關聯關系中的cascade特性的聲明方法。在使用過程中最關鍵點是:腦子中要有一張持久對象關系樹及其狀態圖(狀態分別是:Transient, Persistent, Detached),存在對象間關聯關系時,如果使用了級聯操作特性,要找到樹的根對象(所以要用樹,而不是圖),從根往下級聯操作,只做單方向的級聯。

我們再次使用第一篇的例子,為了反映兩者的關聯關系,為User類我們聲明如下一對多關系

<class name="User" table="USER">
...
<set name="preferences"
cascade="all,delete-orphan"
inverse="true">
<key column="USER_ID" not-null="true"/>
<one-to-many class="Preference"/>
</set>
...
</class>

而為Preference類聲明如下多對一關系

<class name="Preference" table="PREFERENCE">
...
<many-to-one name="user" column="USER_ID" not-null="true"
foreign-key="ALLPREFERENCES" class="User"/>
...
</class>

由上可見,在User和Preference的關系樹中,User是根(root),另外還可以看到為Preference聲明了一個not- null的外鍵。在理清了級聯的順序關系後,後續的持久化操作可以只對User進行即可,Preference的持久化由級聯操作完成。

根據Hibernate的原理和官方建議,應該采用以下持久化方法:

session.save():用於將Transient狀態的對象及其級聯對象持久化(即在該session中,處於persistent狀態),例如,創建新對象及其關聯。

session.flush()或者事務提交(commit)操作:用於將處於presistent狀態的對象修改的持久化,例如,從數據庫將一個關聯樹調到Hibernate中,修改後再次入庫。

session.update(), session.saveOrUpdate(), session.merge():一般只用於處於detached狀態的對象修改後進行的持久化操作(這是Hibernate的一個重要特色,可以很好的處理業務層面的事務(transaction)跟數據庫層面的事務的配合問題),當然,這些方法用於上一種情況也沒有錯

session.delete():刪除對象

做了上述實現後並不能保證關聯關系的級聯操作的正確執行,進一步分析參見後續文章。

在實踐中很容易觸發以下異常:

org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): xxx

這主要是理不清級聯關系造成的,按照本文和下一文介紹的方法可以排除。

還有一個異常:

Cannot delete or update a parent row: a foreign key constraint fails ([外鍵的定義])

其解決方法也是一樣的。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved