-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: bidirectional many-to-many deleting
PostPosted: Fri Nov 14, 2003 3:06 am 
Newbie

Joined: Thu Aug 28, 2003 8:41 pm
Posts: 17
User and Role has a bidirectional many-to-many relationship,
both sides are mapped as cascade="save-update",one side is mapped as inverse="true",the other as inverse="false"

How should I delete a Role(or User) object,
Code:
Role role=(Role)session.load(Role.class,roleId);

session.delete(role);

OR
Code:
Role role=(Role)session.load(Role.class,roleId);

for(Iterator iter=role.getUsers().iterator();iter.hasNext();){
   ((User)iter.next()).getRoles().remove(role);
}

session.delete(role);

I think the second is the right one,but it is very prolix,and may be inefficient.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 3:51 am 
Newbie

Joined: Thu Aug 28, 2003 8:41 pm
Posts: 17
And I find that bidirectional many-to-many is very hard to maintain.

I write the following code to maintain a User's roles, it is very verbose.
Any good idea?
Code:
public static void modifyUserRoles(String userId, String[] roleIds) throws
        HibernateException {
        Session session = openSession();

        User user = (User) session.load(User.class, userId);

        int max = roleIds.length;
        Collection newRoles = new HashSet(max);
        for (int i = 0; i < max; i++) {
            newRoles.add(session.load(Role.class, roleIds[i]));
        }
        //----------------------------------------------------------------------
        //update roles the user no longer has
        for (Iterator iter = user.getRoles().iterator(); iter.hasNext(); ) {
            Role r = (Role) iter.next();
            if (!newRoles.contains(r)) {
                r.getUsers().remove(user);
            }
        }

        //update the user
        user.getRoles().retainAll(newRoles);
        user.getRoles().addAll(newRoles);
        //or just?
        //user.setRoles(newRoles);

        //update roles the user now has
        for (Iterator iter = newRoles.iterator(); iter.hasNext(); ) {
            Role r = (Role) iter.next();
            r.getUsers().add(user);
        }
        //----------------------------------------------------------------------
    }


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 4:21 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
It can be made a lot less verbose by adding helper methods like:

Code:
class Role {

   void removeUser(User user) {
      users.remove(user);
      user.getRoles().remove(this);
   }

   void addUser(User user) {
      user.getRoles().add(this);
      users.add(user);
   }

}


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 5:07 am 
Newbie

Joined: Thu Aug 28, 2003 8:41 pm
Posts: 17
yes,a little better.
but I think it is still inefficient, because lots of roles and their users must be loaded from the database.
bag may be more efficient than set in this case?

Code:
public static void modifyUserRole(String userId, String[] roleIds) throws
        HibernateException {
        Session session = null;
        //session=openSession();

        User user = (User) session.load(User.class, userId);

        int max = roleIds.length;
        Collection newRoles = new HashSet(max);
        for (int i = 0; i < max; i++) {
            newRoles.add(session.load(Role.class, roleIds[i]));
        }
        //----------------------------------------------------------------------
        for (Iterator iter = user.getRoles().iterator(); iter.hasNext(); ) {
            Role r = (Role) iter.next();
            if (!newRoles.contains(r)) {
                r.removeUser(user);
            }
        }

        for (Iterator iter = newRoles.iterator(); iter.hasNext(); ) {
            ( (Role) iter.next()).addUser(user);
        }
        //----------------------------------------------------------------------
}


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 5:20 am 
Newbie

Joined: Thu Aug 28, 2003 8:41 pm
Posts: 17
bags may be worse,when mapped as inverse="false",they always delete all,and than insert.
is that true?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 6:52 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Yes, see section 12 of the reference guide.
You can use idbag to solve this

_________________
Emmanuel


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.