SSH框架下多对多关联关系表的管理中遇到的问题和解决办法


在应用系统最常用的用户与角色管理中,存在多对多关系,一个用户可以拥有多个角色,一个角色可以拥有多个角色,一般设计三个表格,用户表,角色表,和用户-角色表,在用户bean中增加private Set roleSet=new HashSet();角色bean中增加private Set userSet=new HashSet();

    user.hbm.xml中增加

 <set name="roleSet" table="cpms_user_role"
   cascade="save-update" inverse="false" lazy="false">
   <key column="user_code"></key>
   <many-to-many class="com.cpms.bean.CpmsRole"
    column="role_code">
   </many-to-many>
  </set>
  

   role.hbm.xml中增加

 <set name="userSet" table="cpms_user_role"
   cascade="save-update" inverse="true" lazy="false">
   <key column="role_code"></key>
   <many-to-many class="com.cpms.bean.CpmSUSEr"
    column="user_code">
   </many-to-many>
  </set>
 

   这里一开始我双方都用了 inverse="true",导致hibernate根本不管理关系表,都交给对方管理了,就没人管了,我设计的是有用户方管理角色,因此user.hbm.xml中inverse="false".

 在客户端传来选择的角色数据中,我用了一下代码来实现角色的增删改:

String[] roleCodes = rolesStr.split(" ");
  Set<CpmsRole> roleSet = user.getRoleSet();
  // 第一趟遍历, 删除未被选中的角色
  for (Iterator<CpmsRole> it = roleSet.iterator(); it.hasNext();) {
   CpmsRole role = it.next();
   if (!ArrayUtils.contains(roleCodes, role.getCode())) {
    System.out.println("11111111111" + role.getCode());
    role.getUserSet().remove(user);
    it.remove(); // 开始用roleSet.remove(role);抛java.util.ConcurrentModificationException
   }
  }

  // 第二趟遍历 插入新选中的角色
  System.out.println("roleCodes.length"+roleCodes.length);
  for (String roleCode : roleCodes) {
   if (isNewSelected(roleSet, roleCode)) {
    System.out.println("222222222" + roleCode.length()+"222");
    CpmsRole r = userService.getRole(roleCode);
    r.getUserSet().add(user); // 添加用户到角色的关联
    roleSet.add(r);
   }
  }

 

private boolean isNewSelected(Set<CpmsRole> roleSet, String roleCode) {
  if(roleCode.length()<3) return false;
  for (CpmsRole role : roleSet) {
   System.out.println("222222222selecteId" + roleCode+"  "+role.getCode());
   if (role.getCode().indexOf(roleCode)>-1 )
    return false;
  }

  return true;
 }

这个代码在为一个用户分配角色的时候运行结果与预想的相同,但是为第二个用户增加两个以上角色时就出异常

org.springframework.orm.hibernate3.HibernateSystemException: a different object with the same identifier value was already associated with the session: [com.cpms.bean.CpmsRole#101]; nested exception is org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.cpms.bean.CpmsRole#101]
而且删除用户时也出异常:

org.springframework.dao.InvalidDataAccessApiUsageException: deleted object would be re-saved by cascade (remove deleted object from associations): [com.cpms.bean.CpmsUser#user1]; nested exception is org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [com.cpms.bean.CpmsUser#lijianfeng1]

经过分析我认为是hibernate在get一个用户信息的时候会把其它用户已经其它用户的角色也get进来了,在CpmsRole r = userService.getRole(roleCode);
    r.getUserSet().add(user); // 添加用户到角色的关联
    roleSet.add(r);
会导致有两份不同的角色对象,保存就报告异常,我没有想出解决办法,如果你有解决办法请回复告知。

为了实现程序功能,只好变通,把role一方的多对多代码删除,实现了预期功能。删除用户,也能自动把管理表中的该用户的角色一并删除了。

相关内容