1 Reply Latest reply on Jul 24, 2006 4:04 PM by dbatcn

    style and idioms for @ManyToMany definition and update

      Hi,

      I've done plenty of programming with OOP and RDBMS, but am new to the magic world of EJB3/ORM, so I hope somebody could point me in the right direction. I'm building an application with Seam and EJB3 (as well as MyFaces, although I don't think that matters here). I hope this is the proper forum for this question.

      I've got two entity beans, User and Group, with a many-to-many relationship where User is the owner. I have a GroupManagerBean class which is a stateful session bean where I'd like to have a create() method that will create a new group with an initial user. I'm trying to figure out exactly how to annotate the classes and do the data update; my first few attempts haven't worked and I was hoping somebody could offer some advice about how to get this right: cascade types, idioms for object linking and update, etc.

      I've tried to extract the relevant code snippets below. Pointers on how to do this or to previous discussions of this topic gratefully accepted.

      Thanks.

      User.java

      @Entity
      @Name("user")
      @Role(name="currentUser", scope=SESSION)
      @Table(name="USERS")
      public class User implements Serializable {
       ...
       private Set<Group> groups = new HashSet<Group>();
       @ManyToMany(cascade=CascadeType.ALL)
       @JoinTable(name="USER_GROUP",
       joinColumns={@JoinColumn(name="USER_ID")},
       inverseJoinColumns={@JoinColumn(name="GROUP_ID")})
       public Set<Group> getGroups() {
       return groups;
       }
       public void setGroups( Set<Group> groups ) {
       this.groups = groups;
       }
      }
      



      Group.java

      @Entity
      @Name("group")
      @Table(name="GROUPS")
      public class Group implements Serializable {
       ...
       @ManyToMany(cascade=CascadeType.ALL)
       @JoinTable(name="USER_GROUP",
       joinColumns={@JoinColumn(name="USER_ID")},
       inverseJoinColumns={@JoinColumn(name="GROUP_ID")})
       public Set<Group> getGroups() {
       return groups;
       }
       public void setGroups( Set<Group> groups ) {
       this.groups = groups;
       }
      }
      


      GroupManagerBean.java

      @Stateful
      @Name("groupManager")
      @LoggedIn
      public class GroupManagerBean implements GroupManager, Serializable {
       ...
       public void create() {
       group = new Group();
       group.setGroupname( newGroupname() );
       orgmobDatabase.persist( group );
       // User owns the bidirectional many-to-many relationship with Group
       user.getGroups().add( group );
       orgmobDatabase.merge( user );
       orgmobDatabase.refresh( group );
       // PROBLEM:
       // I thought that group.getUsers() would contain user, but it doesn't!
       //debug
       log.debug( "for user "+user+" created group: "+group);
       log.debug( "user "+user+" has "+user.getGroups().size()+" groups");
       log.debug( "group "+group+" has "+group.getUsers().size()+" users");
       for ( Group g : user.getGroups() ) {
       log.debug( "a group for user "+user+": "+g);
       }
       for ( User u : group.getUsers() ) {
       log.debug( "a user for group"+group+": "+u);
       }
       }
      }
      



        • 1. Re: style and idioms for @ManyToMany definition and update

          Adding a flush between the merge and refresh seems to help a lot.

           group = new Group();
           group.setGroupname( newGroupname() );
           orgmobDatabase.persist( group );
           // User owns the bidirectional many-to-many relationship with Group
           user.getGroups().add( group );
           orgmobDatabase.merge( user );
           orgmobDatabase.flush();
           orgmobDatabase.refresh( group );


          Also, after some more reading persistence type PERSIST also seems more appropriate to my needs.