Hibernate @OneToMany 及 @Cascade級聯操作
- 2020 年 3 月 16 日
- 筆記
作者:潘佳琦 鏈接:https://segmentfault.com/a/1190000021857759
前言

image.png
由圖中可以看出實體間關係:一對多(@OneToMany
)
在實際開發場景中,刪除員工老闆不會被刪除,老闆被刪除了員工肯定要刪除
由此,就會使用級聯操作,在一對多關係中,@Cascade
屬性(級聯)只設置「一」的一方即可,外鍵由「多」的一方進行維護。
@ManyToOne和@OneToMany 註解
ManyToOne
(多對一)單向:不產生中間表,但可以用@Joincolumn(name=" ")
來指定生成外鍵的名字,外鍵在多的一方表中產生。OneToMany
(一對多)單向:會產生中間表,此時可以用@onetoMany
@Joincolumn(name=" ")
避免產生中間表,並且指定了外鍵的名字(別看@joincolumn
在一中寫著,但它存在在多的那個表中)OneToMany
,ManyToOne
雙向(兩個註解一起用的):如果不在@OneToMany
中加mappedy
屬性就會產生中間表。
cascade屬性:指定級聯操作的行為(可多選)
- CascadeType.PERSIST:級聯新增(又稱級聯保存):對A對象保存時也會對B對象進行保存。並且,只有A類新增時,會級聯B對象新增。若B對象在資料庫存在則拋異常。對應
EntityManager
的presist
方法。 - CascadeType.MERGE:級聯合併(級聯更新):指A類新增或者變化,會級聯B對象(新增或者變化)。對應
EntityManager
的merge
方法。 - CascadeType.REMOVE:級聯刪除:只有A類刪除時,會級聯刪除B類,即在設置的那一端進行刪除時,另一端才會級聯刪除。對應
EntityManager
的remove
方法。 - CascadeType.REFRESH:級聯刷新:獲取A對象時也重新獲取最新的B對象。對
EntityManager
的refresh(object)
方法。即會重新查詢資料庫里的最新數據(用的比較少) - CascadeType.DETACH:級聯分離。
- CascadeType.ALL:級聯所有操作。
示例(以級聯保存及刪除為例)
Boss老闆實體:
@Entity public class Boss { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @OneToMany(mappedBy = "boss") private List<Staff> staffList; }
Staff員工實體:
@Entity public class Staff { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @ManyToOne private Boss boss; }
不添加任何級聯
執行save
保存操作,結果如下
老闆表:

image.png
員工表:

image.png
執行的SQL:
insert into boss (name) values ('張老闆')
PERSIST:級聯新增(又稱級聯保存)
@OneToMany(mappedBy = "boss", cascade = CascadeType.PERSIST) private List<Staff> staffList;
執行save
保存操作,結果如下
老闆表:

image.png
員工表:

image.png
★員工已經級聯保存,但是員工表中的
boss_id
卻是空,可見級聯是直接將set
中的對象持久化到資料庫,而並沒有對關係進行維護(需要手動去維護)。 」
執行的SQL:
★insert into boss (name) values ('張老闆') insert into staff (boss_id, name) values (1, '員工一') insert into staff (boss_id, name) values (1, '員工二') 」
直接在資料庫中執行SQL關係是維護好的
REMOVE:級聯刪除
@OneToMany(mappedBy = "boss", cascade = CascadeType.REMOVE) private List<Staff> staffList;
執行delete
保存操作,結果如下
老闆表:

員工表:

image.png
執行的SQL
select boss0_.id as id1_0_0_, boss0_.name as name2_0_0_ from boss boss0_ where boss0_.id=1 select stafflist0_.boss_id as boss_id3_2_0_, stafflist0_.id as id1_2_0_, stafflist0_.id as id1_2_1_, stafflist0_.boss_id as boss_id3_2_1_, stafflist0_.name as name2_2_1_ from staff stafflist0_ where stafflist0_.boss_id=1 delete from staff where id=1 delete from staff where id=2 delete from boss where id=1
★老闆表該條記錄刪除,同時員工表中的記錄也被級聯刪除。 」
程式碼
https://github.com/panjiaqi1/Demo