1. cascade定義級聯操做,即"操做完本身"以後下一步作什麼。java
在理解inverse中,Member與MemberCard是一對多的關係,Member級聯save-update MemberCard,因此只要保存membermysql
session.save(member);
memberCard也跟着保存了。git
2. 有時咱們會看到這樣一個級聯配置:cascade="delete-orphan"。sql
annotation中這樣配置session
// orphanRemoval=true級聯更新刪除"脫離"的子節點 @OneToMany(mappedBy = "member", orphanRemoval=true) @Cascade({ CascadeType.SAVE_UPDATE }) private Set<MemberCard> memberCards;
或者app
// CascadeType.DELETE_ORPHAN級聯更新刪除"脫離"的子節點 @OneToMany(mappedBy = "member") @Cascade({ CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN }) private Set<MemberCard> memberCards;
比較新的版本,官方推薦使用orphanRemoval=trueless
public enum CascadeType { ... /** @deprecated use @OneToOne(orphanRemoval=true) or @OneToMany(orphanRemoval=true) */ @Deprecated DELETE_ORPHAN, ...}
這是用於刪除「脫離」的子節點。fetch
Member member = (Member)session.get(Member.class, 1); member.setMemberName("張三2"); Set<MemberCard> memberCards = member.getMemberCards(); // 確認會員有3張會員卡 Assert.assertEquals(3, memberCards.size()); // 從中取出一張會員卡 MemberCard memberCard = memberCards.iterator().next(); // 把這張會員卡移除掉 member.getMemberCards().remove(memberCard); session.update(member);
從上面的代碼中能夠看到只update一下member,在update member以後有一條delete語句,sql輸出以下:ui
Hibernate: select member0_.id as id2_0_, member0_.member_name as member2_2_0_ from member member0_ where member0_.id=? Hibernate: select membercard0_.member_id as member3_2_1_, membercard0_.id as id1_, membercard0_.id as id3_0_, membercard0_.card_no as card2_3_0_, membercard0_.member_id as member3_3_0_ from member_card membercard0_ where membercard0_.member_id=? Hibernate: update member set member_name=? where id=? Hibernate: delete from member_card where id=?
3. cascade:JPA & Hibernate annotation。spa
這裏是很容易讓人誤解的地方。
JPA cascade: javax.persistence.CascadeType
public enum CascadeType { /** Cascade all operations */ ALL, /** Cascade persist operation */ PERSIST, /** Cascade merge operation */ MERGE, /** Cascade remove operation */ REMOVE, /** Cascade refresh operation */ REFRESH}
Hibernate cascade:org.hibernate.annotations.CascadeType
public enum CascadeType { ALL, PERSIST, MERGE, REMOVE, REFRESH, DELETE, SAVE_UPDATE, REPLICATE, /** @deprecated use @OneToOne(orphanRemoval=true) or @OneToMany(orphanRemoval=true) */ @Deprecated DELETE_ORPHAN, LOCK, /** @deprecated use javax.persistence.CascadeType.DETACH */ @Deprecated EVICT, DETACH}
有時咱們這樣配置,這裏應用的是JPA cascade
@OneToMany(mappedBy = "member", fetch = FetchType.LAZY, cascade={CascadeType.PERSIST}) private Set<MemberCard> memberCards;
保存member,發現memberCard沒有跟着保存,除非使用CascadeType.ALL,不然其餘的都沒有用。
session.save(member);
sql輸出
Hibernate: insert into member (id, member_name) values (null, ?)
可是session.persist()卻能夠級聯保存
session.persist(member);
sql輸出
Hibernate: insert into member (id, member_name) values (null, ?) Hibernate: insert into member_card (id, card_no, member_id) values (null, ?, ?) Hibernate: insert into member_card (id, card_no, member_id) values (null, ?, ?) Hibernate: insert into member_card (id, card_no, member_id) values (null, ?, ?)
若是咱們想session.save()方法有效果,能夠使用hibernate cascade:
@OneToMany(mappedBy = "member", fetch = FetchType.LAZY) @Cascade({ CascadeType.SAVE_UPDATE }) private Set<MemberCard> memberCards;
再試一下
session.save(member);
sql輸出
Hibernate: insert into member (id, member_name) values (null, ?) Hibernate: insert into member_card (id, card_no, member_id) values (null, ?, ?) Hibernate: insert into member_card (id, card_no, member_id) values (null, ?, ?) Hibernate: insert into member_card (id, card_no, member_id) values (null, ?, ?)
從上面的實踐中,大概能夠知道cascade的類型粗略的對應着session的一個方法。更詳細的內容能夠查看hibernate源碼 org.hibernate.engine.Cascade/org.hibernate.engine.CascadeStyle/org.hibernate.engine.CascadingActiona
cascade說明級聯操做,操做完本身以後下一步作什麼;inverse說明由誰來維護外鍵的值。
更多參考hibernate demo