程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Hibernate(JPA)多對多(ManyToMany)關聯映射不完美之處

Hibernate(JPA)多對多(ManyToMany)關聯映射不完美之處

編輯:關於JAVA

近來,在做的一個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)這種能力!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved