hibernate cascade
1. cascade定义级联操作,即"操作完自己"之后下一步做什么。
在理解inverse中,Member与MemberCard是一对多的关系,Member级联save-update MemberCard,所以只要保存member
session.save(member);
memberCard也跟着保存了。
2. 有时我们会看到这样一个级联配置:cascade="delete-orphan"。
annotation中这样配置
// orphanRemoval=true级联更新删除"脱离"的子节点 @OneToMany(mappedBy = "member", orphanRemoval=true) @Cascade({ CascadeType.SAVE_UPDATE }) private Set<MemberCard> memberCards;
或者
// CascadeType.DELETE_ORPHAN级联更新删除"脱离"的子节点 @OneToMany(mappedBy = "member") @Cascade({ CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN }) private Set<MemberCard> memberCards;
比较新的版本,官方推荐使用orphanRemoval=true
public enum CascadeType { ... /** @deprecated use @OneToOne(orphanRemoval=true) or @OneToMany(orphanRemoval=true) */ @Deprecated DELETE_ORPHAN, ...}
这是用于删除“脱离”的子节点。
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输出如下:
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。
这里是很容易让人误解的地方。
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 vs inverse(mappedBy)
cascade说明级联操作,操作完自己之后下一步做什么;inverse说明由谁来维护外键的值。
更多参考hibernate demo
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。