隨筆-42  評論-578  文章-1  trackbacks-0
          近來,在做的一個NewsMS項目中,需要用到多對多關聯映射,以下是項目中用到的兩個實體類:用戶類User和角色類Role,它們之間是多對多的關系。
          //用戶表
          @Entity
          @Table(name
          ="rong_user")
          public class User{

              
          //省略其它內容

              
          private Set<Role> roles = new LinkedHashSet<Role>();    //角色集合
              
              @ManyToMany(cascade 
          = {CascadeType.PERSIST, CascadeType.MERGE})
              @JoinTable(name 
          = "rong_user_role", joinColumns = { @JoinColumn(name ="user_id" )}, inverseJoinColumns = { @JoinColumn(name = "role_id") })
              @OrderBy(
          "id")
              
          public Set<Role> getRoles() {
                  
          return roles;
              }

              
          public void setRoles(Set<Role> roles) {
                  
          this.roles = roles;
              }

          }

          //角色表
          @Entity
          @Table(name
          ="rong_role")
          public class Role{
              
              
          //省略其它內容

              
          private Set<User> user = new LinkedHashSet<User>();        //用戶集合

              @ManyToMany(cascade 
          = {CascadeType.PERSIST, CascadeType.MERGE}, mappedBy = "roles", fetch = FetchType.LAZY)
              
          public Set<User> getUser() {
                  
          return user;
              }

              
          public void setUser(Set<User> user) {
                  
          this.user = user;
              }

          }


                   這兩個生成數據庫中的三個表,分別是rong_user, rong_role和一個中間表rong_user_role。
                   Hibernate和JPA控制關聯關系的,只能是一方,不能雙方控制的,上面的程序中,我通過在Role類中設置mappedBy="roles"來設置由User來控制關系,
                   這樣,問題就出現了:當我在要刪除角色Role時,如果沒有用戶擁有這個角色的話,就能成功刪除;如果有用戶擁有這個角色的時候,就不能刪除,會拋以下異常:
          12:53:33,125  WARN JDBCExceptionReporter:100 - SQL Error: 1451, SQLState: 23000
          12:53:33,125 ERROR JDBCExceptionReporter:101 - Cannot delete or update a parent row: a foreign key constraint fails (`newsms/rong_user_role`, CONSTRAINT `FKF1698421A337A5FA` FOREIGN KEY (`role_id`) REFERENCES `rong_role` (`id`))
          12:53:33,171 ERROR AbstractFlushingEventListener:324 - Could not synchronize database state with session
          org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
          /****堆棧信息略****/
          Caused by: java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key constraint fails (`newsms/rong_user_role`, CONSTRAINT `FKF1698421A337A5FA` FOREIGN KEY (`role_id`) REFERENCES `rong_role` (`id`))
          /******堆棧信息略*****/

                當我設置成單向關系映射時,即把Role類中,Set<User>信息去掉,這樣,也不能刪,原因也是說有外鍵約束!怎么辦?
                苦惱了好幾天,最后,只能歸于Hibernate(JPA)的多對多關聯映射設計得有點不符實際!就像上面我說的例子,有人選了某角色,就不能刪掉該角色。還有一種做法是,在Role類中:
          @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE,CascadeType.REMOVE}, mappedBy = "roles", fetch = FetchType.LAZY)
              
          public Set<User> getUser() {
                  
          return user;
              }
                  即加多一個“CascadeType.REMOVE”,這樣能把角色Role給刪掉了,但連擁有該角色的所有用戶User也被級聯刪掉了。這樣來看,某個用戶擁有許多角色,就因為其中有這一個角色,就被級聯刪了整個自己,那不是很冤枉。這也不符合實際!
                  個人認為,Hibernate(JPA)在設置多對多關聯映射時,應該有做法能使得雙方都能控制關聯關系才好,才符合實際吧!但事實上,好像還沒有發現有Hibernate(JPA)這種能力!


          本文原創,轉載請注明出處,謝謝!http://www.aygfsteel.com/rongxh7(心夢帆影JavaEE技術博客)
              

          posted on 2009-06-08 13:33 心夢帆影 閱讀(26957) 評論(15)  編輯  收藏 所屬分類: HibernateJPA

          評論:
          # re: Hibernate(JPA)多對多(ManyToMany)關聯映射不完美之處 2009-06-08 18:18 | 虎嘯龍吟
          這樣就是符合實際啊:當某個用戶擁有某個角色的時候,不應該刪除該角色吧!  回復  更多評論
            
          # re: Hibernate(JPA)多對多(ManyToMany)關聯映射不完美之處 2009-06-08 18:26 | 心夢帆影
          @虎嘯龍吟
          用戶與角色是多對多的關系,如果系統不需要或個角色了,而因為有用戶跟這個角色有關聯,而刪不了!那怎么對角色進行管理?只能添加,修改,不能刪除?  回復  更多評論
            
          # re: Hibernate(JPA)多對多(ManyToMany)關聯映射不完美之處 2009-06-08 19:20 | YangL
          LZ也在用SpringSide吧,呵呵  回復  更多評論
            
          # re: Hibernate(JPA)多對多(ManyToMany)關聯映射不完美之處 2009-06-08 21:01 | 心夢帆影
          @YangL
          被你看穿了,呵呵
          但我沒有直接把Springside當組件用,而是學習它!
          有興趣交流一下不?我QQ:121040245,呵呵  回復  更多評論
            
          # re: Hibernate(JPA)多對多(ManyToMany)關聯映射不完美之處 2009-06-08 21:18 | 小人物
          學習了!  回復  更多評論
            
          # re: Hibernate(JPA)多對多(ManyToMany)關聯映射不完美之處 2009-06-09 20:44 | huliqing
          這不應該是hibernate的不完美之處,數據庫的這個作法是正確的,這涉及到數據完整與安全性的問題。我認為你應該先明確的處理掉相關的持有該角色的相關用戶的對于該角色的關系。也就是說先刪除相關用戶對該角色的持有關系,再刪除該角色就沒有問題。
          或者選擇不作外鍵約束,但是這樣就會對比較嚴格的系統造成數據冗余,不完整,還包括安全問題。  回復  更多評論
            
          # re: Hibernate(JPA)多對多(ManyToMany)關聯映射不完美之處 2009-06-11 00:33 | 虎嘯龍吟
          @YangL
          可以先去掉該用戶的角色,再刪除該角色啊  回復  更多評論
            
          # re: Hibernate(JPA)多對多(ManyToMany)關聯映射不完美之處 2012-12-23 11:32 | lin
          雙方都用OneToMany就行了  回復  更多評論
            
          # re: Hibernate(JPA)多對多(ManyToMany)關聯映射不完美之處[未登錄] 2013-06-15 13:01 | James
          關聯關系不要雙方配置 只在主表配置  回復  更多評論
            
          # re: Hibernate(JPA)多對多(ManyToMany)關聯映射不完美之處[未登錄] 2013-06-15 13:03 | James
          @ManyToMany(cascade={CascadeType.PERSIST,CascadeType.MERGE})
          @JoinTable(name = "adgroup_ad", joinColumns = { @JoinColumn(name = "adgroup_id") }, inverseJoinColumns = { @JoinColumn(name = "ad_version_id") })
          這是我的項目的主表部分的注解配置 測試增加修改都可以 刪除也只刪除關聯關系  回復  更多評論
            
          # re: Hibernate(JPA)多對多(ManyToMany)關聯映射不完美之處[未登錄] 2013-06-15 13:10 | James
          汗 SORRY 發現我的問題和你的不一樣的 我這里還是會出現你說的這種情況 SORRY 看來它還真是設計有點不合理的  回復  更多評論
            
          # re: Hibernate(JPA)多對多(ManyToMany)關聯映射不完美之處 2013-09-02 10:49 | phevose
          這在業務邏輯上是完全合理的,正在被使用的角色是不應該被刪除的,如果刪除那么應該做級聯刪除,對應的用戶也應該一并刪除,或者應該先解除關聯關系后再刪除該角色。  回復  更多評論
            
          # re: Hibernate(JPA)多對多(ManyToMany)關聯映射不完美之處 2014-11-14 16:16 | 雪妮星跡
          樓主想要的級聯功能,可以使用數據庫的外鍵約束控制。  回復  更多評論
            
          # re: Hibernate(JPA)多對多(ManyToMany)關聯映射不完美之處 2015-01-27 15:20 | lp
          @心夢帆影
          可以不建立外鍵關聯,通過應用控制數據的完整性。  回復  更多評論
            
          # re: Hibernate(JPA)多對多(ManyToMany)關聯映射不完美之處 2016-04-07 15:10 | coolcjava
          只有兩個實體類都配置了joinColumns和inverseJoinColumns屬性,并且位置互相調換,就可以使用雙向維護  回復  更多評論
            
          主站蜘蛛池模板: 龙门县| 石景山区| 城步| 抚松县| 湖口县| 中阳县| 石屏县| 轮台县| 且末县| 临猗县| 平乐县| 通城县| 成都市| 荣昌县| 阿瓦提县| 滦平县| 乌鲁木齐市| 焉耆| 阿荣旗| 铅山县| 黑山县| 阿克苏市| 合川市| 苏尼特右旗| 娄烦县| 桂林市| 饶河县| 灵山县| 牙克石市| 安吉县| 峨眉山市| 额尔古纳市| 西林县| 申扎县| 开鲁县| 邮箱| 云和县| 宜黄县| 沂源县| 林州市| 乐安县|