MySQL和Hibernate的cascade用法區別

在數據庫裏,進行增加、修改、刪除記錄的時候,經常會涉及到父子關係的表。

例如:有省份表和城市表,其中城市表有一個外鍵province_id引用到省份表的主鍵。這樣,可以把省份表看成是父表,把城市表看成是子表,城市表記錄的存在依賴於省份表的記錄。(文中提到的例子,所有的代碼在附件裏都有,所以這裏的描述從簡)

一、在MySQL裏的cascade

以下直接在MySQL的控制檯操作省份表和城市表

在省份表增加一條“廣東”的記錄,在城市表增加一條“廣州”的記錄,並且把“廣州”的外鍵引用到“廣東”的主鍵。“廣州”的存在依賴於“廣東”,如果刪除省份表的“廣東”,將會影響到城市表的“廣州”。根據城市表的外鍵約束的on delete設置,有如下三種情況:

1、外鍵沒有on delete的設置:當刪除“廣東”的時候,MySQL會報錯,刪除失敗。

2、外鍵設置爲on delete cascade:當刪除“廣東”的時候,同時把“廣州”也刪除。

3、外鍵設置爲on delete set null:當刪除“廣東”的時候,“廣州”的外鍵province_id會被自動設置爲null,即“廣州”脫離了對“廣東”的依賴關係。

二、在Hibernate裏的cascade

以下用Hibernate來操作省份表和城市表

首先,在hibernate.cfg.xml文件配置好連接MySQL數據庫的相關屬性(請在那裏修改登陸數據庫的密碼)。然後,爲省份表和城市表添加相關的POJO類和XML映射文件。用SQL語句建表(在附件的test_cascade.sql裏),城市表有一個外鍵province_id引用到省份表的主鍵,並把這個外鍵設置爲on delete cascade。這個外鍵約束,在Hibernate變成了雙向的映射關係:City類有一個類型爲Province的province屬性,關聯到省份表,在映射文件中是many-to-one的關係;Province類有一個Set<City>的cities屬性,關聯到城市表,在映射文件中是one-to-many的關係。

在Hibernate的映射文件裏,同樣可以設置cascade屬性來控制父子關係。通常在父表設置cascade屬性,有以下幾種情況:

1、沒有設置cascade屬性

用方法addInNoCascade()增加記錄“廣東”和“廣州”(方法在類CityManager裏,以下同),再用方法delete()刪除“廣東”,將會出現異常,系統會說因爲“廣東”被城市表外鍵關聯了而不能刪除。用SQL建表時,已經把外鍵設爲on delete cascade,怎麼不能把“廣東”刪除的同時,級聯刪除“廣州”呢?用MyEclipse查看城市表,發現有兩個外鍵,如圖所示:



第2個外鍵是用SQL建表時生成的,設置了on delete cascade;而第1個外鍵應該是用Hibernate操作數據庫時,Hibernate自動建立的。第1個外鍵的On delete被設置爲No action,因此刪除“廣東”的時候,受到這個外鍵的限制,導致刪除失敗。

2、設置cascade屬性爲delete-orphan

在映射文件Province.hbm.xml中,在one-to-many關係對應的Set裏,設置cascade="delete-orphan",此功能與MySQL裏設置外鍵設置爲on delete cascade相同。再用方法delete()刪除“廣東”,刪除成功。即是,設置cascade爲delete-orphan以後,對刪除父表記錄的時候,會同時刪除子表的相關記錄。

3、設置cascade屬性爲all

cascade的屬性,除了可以是delete-orphan,還可以是create、update、delete、all等等。all代表除 delete-orphan以外的所有屬性值,當設置cascade爲all以後,對父表記錄的增加、修改操作,會影響到子表的相關記錄。

在映射文件Province.hbm.xml中,在one-to-many關係對應的Set裏,設置cascade="all"。用方法 addInCascadeOfAll()增加記錄“廣東”,方法裏只有save“廣東”,並沒有save“深圳”,只是用屬性關聯了“廣東”和“深圳”的關係。結果顯示,深圳也被添加到數據庫裏,這就是cascade="all"的作用,使對父表的操作影響到子表。

注意:A、delete-orphan是一個特別的屬性值,只能應用在one-to-many關係的cascade屬性。B、cascade屬性通常在one-to-one和one-to-many關係裏應用,不推薦在many-to-one或者many-to- many關係裏應用。

三、總結

1、MySQL裏設置cascade和在Hibernate設置cascade是不同的。在MySQL裏設置了cascade,並不能對Hibernate的操作起到作用,原因是Hibernate自動爲子表添加了外鍵。

2、使用級聯(cascade)功能,方便了數據庫的操作,使得操作一個表的記錄會影響到其他表的記錄。但是,級聯功能會帶來安全隱患。特別是在 Hibernate裏,修改一個POJO對象的映射引用屬性,會導致該引用屬性所對應的POJO對象受到影響。例如,把“廣東”的 Set<City>類型的cities屬性清空(即對集合Set調用clear()方法),則會導致把引用“廣東”的“深圳”刪除了。因此,使用級聯功能時要小心謹慎。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章