關於Hibernate 串聯更新 不刪除資料的問題

來源:互聯網
上載者:User

幾個相關表的關係:
Announcement(公告)   1       >      n        AnnounceRole(公告對應角色)      n      <       1      Role(角色)

問題:hibernate 在操作級聯add和delete時,Announcement和AnnounceRole都可以正常反應到資料庫裡,但更新時發現,Announcement的資料正常更新,但AnnounceRole的資料只増不減,解決此問題可以參考以下配置。

首先需要注意的地方就是,問題出現時,更新是通過JSP的FORM使Announcement對象初始化並賦值,將此對象傳遞給getHibernateTemplate().update()進行調用的,此時Announcement對象是新的,如果直接使用此對象進行更新並不會反應到曆史資料的處理上。
正確的邏輯是在更新前,先調用getHibernateTemplate().get()返回Announcement對象,在此對象的基礎上對各個屬性set,而annRoles屬性不可以set(new Set()),只可以在原有的集合上進行remove和add,否則在update時會報”A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance“的異常。此例中新增一個addAnnRole()代替setAnnRoles()。

相關的Entity

public class Announcement{private String annID;private Set<AnnounceRole> annRoles;public Set<AnnounceRole> getAnnRoles(){return this.annRoles;}// 設定為private兩個方面,1:Entity需要此屬性的set(),2:用addAnnRole()代替private void setAnnRoles(Set<AnnounceRole> annRoles){this.annRoles=annRoles;}// 用此方法代替setAnnRoles()public void addAnnRole(AnnounceRole annRole){getAnnRoles().add(annRole);}}public class AnnounceRole{private String annID;private String roleID;        private Role role;        .......}public class Role{private String roleID;private String roleName;        .......}

*上述表示的為單向的級聯關係

相關的hbm.xml

<hibernate-mapping><class name="Announcement" table="Announcement" ><id name="annID" type="java.lang.String" ><column name="annID" length="10" not-null="true" /><generator class="assigned"/></id><set name="annRoles" lazy="extra" cascade="all-delete-orphan" inverse="true"><key column="annID" /><one-to-many class="AnnounceRole" /></set></class></hibernate-mapping><hibernate-mapping><class name="AnnounceRole" table="AnnounceRole" ><composite-id> <key-property name="annID" type="java.lang.String" column="annID" /> <key-property name="roleID" type="java.lang.Integer" column="roleID" /> </composite-id> <many-to-one name="role" class="Role" column="roleID" unique="true" lazy="proxy" insert="false" update="false"/></class></hibernate-mapping><hibernate-mapping><class name="Role" table="Role" ><id name="roleID" type="java.lang.String" ><column name="roleID" length="10" not-null="true" /><generator class="assigned"/></id><property name="roleName" type="java.lang.String"><column name="roleName" length="20" not-null="true"/></property></class></hibernate-mapping>

<set name="annRoles" lazy="extra" cascade="all-delete-orphan" inverse="true">
<key column="annID" />
<one-to-many class="AnnounceRole" />
</set>

cascade="all-delete-orphan" inverse="true"此處的含義

cascade="all-delete-orphan",更新歷史資料需要此設定

inverse="true",控制權交給AnnounceRole,否則在update時,會對AnnounceRole表的annID賦NULL值,而表中又定義此欄位NOT NULL,所以會報SQL異常。

實際執行代碼

announcement.getAnnRoles().clear();....announcement.addAnnRole(annRole);

getHibernateTemplate().clear();getHibernateTemplate().update(announcement)

announcement.getAnnRoles()實際上是PersistentSet,裡面儲存了SessionImpl的執行個體,在調用Set 的 clear()時,沒有清除session中的annRole資訊。這導致下面的情況,annRole存在於PersistentSet中,調用clear()清除掉後,在announcement.addAnnRole(annRole)又插入了相同的執行個體,此時session中就儲存了兩個主鍵相同的annRole對象,最後在update時拋出“org.springframework.dao.DuplicateKeyException:
a different object with the same identifier value was already associated with the session”異常,所以在getHibernateTemplate().update(announcement)之前clear,此處感覺clear處理的方式不是很友好,希望有更好的辦法。

至此問題就可以解決了,如果文中描述有問題或者您有更好的解決方案,歡迎留言。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.