EJB3 支持的操作類型
/** * Cascade types (can override default EJB3 cascades */ 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 }
級聯更新保存
@JoinColumn(name = "conf_file_id", referencedColumnName = "conf_file_id",insertable = true,updatable = true) @Cascade(value = {org.hibernate.annotations.CascadeType.SAVE_UPDATE})
級聯刪除
@OneToMany(mappedBy = "projectByProPlanId",orphanRemoval=true) @Cascade(value = {org.hibernate.annotations.CascadeType.SAVE_UPDATE})
save-update: 級聯保存(load以后如果子對象發生了更新,也會級聯更新). 但它不會級聯刪除
delete: 級聯刪除, 但不具備級聯保存和更新
all-delete-orphan: 在解除父子關系時,自動刪除不屬於父對象的子對象, 也支持級聯刪除和級聯保存更新.
all: 級聯刪除, 級聯更新,但解除父子關系時不會自動刪除子對象.
delete-orphan:刪除所有和當前對象解除關聯關系的對象
注意:以上設在哪一段就是指對哪一端的操作而言,比如delete,如果設在one的一端的<set>屬性里,就是當one被刪除的時候,自動刪除所有的子記錄;
如果設在many一端的<many-to-one>標簽里,就是在刪除many一端的數據時,會試圖刪除one一端的數據,如果仍然有many外鍵引用one,就會報“存在子記錄”的錯誤;如果在one的一端同時也設置了cascade=“delete”屬性,就會發生很危險的情況:刪除many一端的一條記錄,會試圖級聯刪除對應的one端記錄,因為one也設置了級聯刪除many,所以其他所有與one關聯的many都會被刪掉。
所以,千萬謹慎在many一端設置cascade=“delete”屬性。
故此cascade一般用在<one-to-one>和<one-to-many>中
以下轉載自:http://blog.csdn.net/sinlff/article/details/7342527
很多人對持久層概念搞不清JPA、Hibernate、EJB3.0的關系,這里做一下簡單的說明:JPA是一個持久層設計接口,EJB3.0和Hibernate是具體的實現類,EJB3.0和Hibernate的功能近似相等的(Hibernate沒有Session Bean,Spring MVC3的SessionAttribute跟Session Bean近似)。
理論是使用JPA接口可以無縫切換持久層實現,但是僅僅是理論上!!!
JPA是在Hibernate成熟並大行其道的時候才推出的,基本上是借鑒Hibernate的優點,做了一個統一的標准而已,JPA1.0沒有一對多的級聯刪除配置,也許JPA2.0里才有吧(這里沒做過調研)
@OneToMany(mappedBy = "commentTeam")
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE,org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
private Set<CommentTeamMember> commentTeamMembers;
這里為了說明,只貼出一對多的關鍵代碼,其它無關的注解已忽略掉,以免造成干擾。
這里重點說明一下四個常用的注解配置的區別:
CascadeType.SAVE_UPDATE
CascadeType.ALL
CascadeType.DELETE
CascadeType.DELETE_ORPHAN
之所有之列出這四個,是因為我不想跟書本上把所有的概念都羅列出來。基本上開發時其中的3個都以及足夠用了,下面我結合代碼演示一下他們之間的區別,以及使用的時候注意的地方。
CascadeType.SAVE_UPDATE:Hibernate專有的,JPA並不支持,作用是級聯保存、級聯更新(注:JPA很惡心,要么你配置
CascadeType.ALL,要么你配CascadeType.SAVE+CasadeType.Merge。八卦一句:專家雖牛,多年不寫代碼,定的標准讓編碼麻煩呀!)
CascadeType.ALL:級聯保存、修改、刪除、同步,一般很少用,看看控制台的一長串SQL就知道性能低下,你沒改的關聯表也給你發update語句,我從來沒用過這個屬性。
CascadeType.DELETE:當調用session.delete(A)的時候,級聯刪除關聯的對象。(注:先調用A.setB(null),再調用session.delete(A),這樣是級聯刪不掉B的。
CascadeType.DELETE_ORPHAN:一對多級聯刪除。
下面重點來說說這個CascadeType.DELETE_ORPHAN:
看過API、開發指南,級聯刪除就一個經典的
@OneToMany(mappedBy = "commentTeam")
@Cascade({CascadeType.SAVE_UPDATE,CascadeType.DELETE_ORPHAN})
private Set<CommentTeamMember> commentTeamMembers;
mappedBy不可少,映射A->B一對多的另一邊控制反轉(誰控誰的問題),新版的Hibernate3.4中配置更簡單,變一句了,更簡潔吧?
@OneToMany(mappedBy = "commentTeam",orphanRemoval=true)
private Set<CommentTeamMember> commentTeamMembers;
CommentTeam commentTeam=this.getHibernateTemplate.get(CommentTeam.class,id);
commentTeam.setCommentTeamMember(null);//想級聯刪除子表數據
this.getHibernateTemplate.saveOrUpdate(commentTeam);
這樣級聯刪除卻沒有發生,為什么呢?
再來一個例子
CommentTeam commentTeam=this.getHibernateTemplate.get(CommentTeam.class,id);
Set<CommentTeamMember> commentTeamMembers=new HashSet<CommentTeamMember>();
commentTeam.setCommentTeamMember(commentTeamMembers);//想級聯刪除子表數據或增減替換對象
this.getHibernateTemplate.saveOrUpdate(commentTeam);
這個例子級聯刪除的效果也沒發生!即使commentTeamMembers里有若干個對象。
成功執行級聯刪除的語法:
CommentTeam commentTeam=this.getHibernateTemplate.get(CommentTeam.class,id);
commentTeam.getCommentTeamMember().clear();//注意這里引用的集合還是原來的集合,這里沒有重新new過
commentTeam.getCommentTeamMember().add(new CommentTeamMember());//如果想替換為新的集合可以用addAll方法
this.getHibernateTemplate.saveOrUpdate(commentTeam);
分析一下原因:級聯刪除起作用的前提是關聯的集合對象不能重新指向新的引用,必須在原有的集合里操作新增、刪除、清空元素,像上面的setXXX(null)的方法等是起不到級聯刪除作用的,大概是Hibernate自認自己原生的集合對象吧,自己New的放進行級聯刪除無效!