Hibernate删除关系manyToMany

时间:2012-08-31 20:49:12

标签: java spring hibernate java-ee

我有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的副本,不确定这是否有帮助。再次感谢!

(添加角色效果很好)

enter image description here

3 个答案:

答案 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;
    }

希望将来可以对其他人有所帮助!

再次感谢大家的帮助!