在应用系统最常用的用户与角色管理中,存在多对多关系,一个用户可以拥有多个角色,一个角色可以拥有多个角色,一般设计三个表格,用户表,角色表,和用户-角色表,在用户bean中增加private Set roleSet=new HashSet();角色bean中增加private Set userSet=new HashSet();
user.hbm.xml中增加
<set table="cpms_user_role"
cascade="save-update" inverse="false" lazy="false">
<key column="user_code"></key>
<many-to-many
column="role_code">
</many-to-many>
</set>
role.hbm.xml中增加
<set table="cpms_user_role"
cascade="save-update" inverse="true" lazy="false">
<key column="role_code"></key>
<many-to-manyhttps://www.linuxidc.com/topicnews.aspx?tid=3" target="_blank" title="SUSE">SUSEr"
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一方的多对多代码删除,实现了预期功能。删除用户,也能自动把管理表中的该用户的角色一并删除了。