ManyToMany关联映射

以下是两个实体类:用户类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.     delete之前,打破这种关联关系,可以设定关系为null,用role.setUser(null);

2.     cascade=CascadeType.ALL改为cascade={CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH},即去掉REMOVE

3.     使用s.createQuery("delete from Role r where r.id=1");


你可能感兴趣的:(ManyToMany关联映射)