我有3个表Role,User和UserRole。表UserRole包含用户和角色之间的映射以及两个相应的索引列。我正在使用hibernate注释,并希望能够从用户“撤销”一个角色,但这有点困难。
在我的用户类中,我有
@ManyToMany(fetch=FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST}, targetEntity = Role.class)
@IndexColumn(name = "role_index", base = 0)
@NotFound(action=NotFoundAction.IGNORE)
@JoinTable(name = "tblUser_Role", joinColumns={
@JoinColumn(name = "UID")}, inverseJoinColumns={
@JoinColumn(name = "roleid", nullable = false)})
private List<Role> roles = new ArrayList<Role>(0);
在我的角色课程中我有
@ManyToMany(fetch=FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST}, mappedBy="roles")
private List<User> users = new ArrayList<User>(0);
和我呼吁“撤销”角色的DAO方法是
@Override
public boolean revokeRolesFromUserAccount(User user, List<Role> userRoles) {
if (log.isInfoEnabled()) {
log.info("Roles revoked from the User " + user.getUsername());
}
if (user == null) {
return false;
}
if (userRoles == null) {
return false;
}
Iterator<Role> iter = userRoles.iterator();
List<Role> newroles = new ArrayList<Role>(0);
Role role = null;
while (iter.hasNext()) {
role = (Role) this.sessionFactory.getCurrentSession().load(
Role.class, iter.next().getRoleid());
newroles.add(role);
}
User newUser = null;
newUser = (User) this.sessionFactory.getCurrentSession().load(User.class, user.getUid());
newUser.getRoles().removeAll(newroles);
this.sessionFactory.getCurrentSession().saveOrUpdate(newUser);
return true;
}
由于某种原因,这不能按预期工作,突破时我注意到角色没有被初始化我想由于LazyLoading,我尝试做类似Hibernate.initialize(newUser.getRoles())
的事情,但这并没有改变任何东西。我仍在学习hibernate的绳索,我不确定我错过了什么,也许是非常明显的事情?非常感谢你提前的时间和想法!
更新:在尝试Paujo和Matin Kh建议的修复并进行进一步调试之后,我仍然没有看到在行newUser = (User) this.sessionFactory.getCurrentSession().load(User.class, user.getUid());
后加载的角色有任何差异
这是我的tblUser_Role的副本,不确定这是否有帮助。再次感谢!
(添加角色效果很好)
答案 0 :(得分:1)
我在这里遇到了确切的情况。你的问题有一个非常简单的解决方案。
对于其中一个班级,请使用EAGER
,而另一个班级则使用LAZY
。试试这个:
作用:
@ManyToMany(fetch=FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST}, mappedBy="roles")
private List<User> users = new ArrayList<User>(0);
用户:
@ManyToMany(fetch=FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST}, targetEntity = Role.class)
@IndexColumn(name = "role_index", base = 0)
@NotFound(action=NotFoundAction.IGNORE)
@JoinTable(name = "tblUser_Role", joinColumns={
@JoinColumn(name = "UID")}, inverseJoinColumns={
@JoinColumn(name = "roleid", nullable = false)})
private List<Role> roles = new ArrayList<Role>(0);
答案 1 :(得分:0)
我认为你的方法应该是不同的。
UserRole应该有角色名称。
您的用户应该有一个UserRole项目列表,或者只有一个UserRole但具有UserRole层次结构。但是你有一个好的清单。
所以基本上你在User到UserRole中有引用所以不需要在UserRole中引用User。
这样你的表变得非常简单,你不需要任何连接就可以了,你可以按名称选择UserRole。
之后,您应该可以从User中的UserRole列表中删除引用并合并用户。
答案 2 :(得分:0)
最后得到了这个工作,主要是纯粹的运气,这是我在RoleDaoImpl类中最终得到的结果。
@Override
@Transactional
public boolean revokeRolesFromUserAccount(User user, List<Role> userRoles) {
if (user == null) {
return false;
}
if (userRoles == null) {
return false;
}
User newUser = null;
newUser = (User) this.sessionFactory.getCurrentSession().load(User.class, user.getUid());
List<Role> newRoleList = newUser.getRoles();
newRoleList.removeAll(userRoles);
if(newUser.getRoles().retainAll(newRoleList)){
if (log.isInfoEnabled()) {
log.info("Roles revoked from the User " + user.getUsername());
}
this.sessionFactory.getCurrentSession().saveOrUpdate(newUser);
return true;
}else{
return false;
}
希望将来可以对其他人有所帮助!
再次感谢大家的帮助!