談論Hibernate級聯刪除——JPA根據Hibernate實現許多級聯刪除CascadeType.DELETE_ORPHAN


聲明:
1、這篇文章是原創。非復制或轉載過來。
2、在本文中,參數都親自做過實驗證明。
3、這篇文章談到了Hibernate配置基於注釋的方法。hbm語法不可用。
不清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;


以上兩種配置方式是等價的,以下是在實際開發中的使用了,有些時候代碼方面不注意,會誤以為明明配置正確了。但為什么不起作用呢? 以下例舉一下代碼,請看Action代碼(實際上我在Spring Controller里。N年不寫DAO了,Service非常少用,Manager一邊去!


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的放進行級聯刪除無效!




































































































免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM