6 Replies Latest reply on May 1, 2005 6:05 PM by Emmanuel Bernard

    ManyToMany: Howto use

    Darko Krizic Newbie

      Hi!

      I have [User] <- ManyToMany -> [Group]

      User#getGroups() is FetchType.EAGER.

      How do I use this? I have a Session Bean where I have this method:

      public void addGroupToUser(Group g, User u) {
      u = em.merge( u );
      g = em.merge( g );
      u.getGroups().add( g );
      em.merge( u );
      }


      But this does not work. What is wrong?

        • 1. Re: ManyToMany: Howto use
          Emmanuel Bernard Master

          You don't have to use merge on the same object twice, this is a no op.
          We aware that the user.getGroups() has to be the owner side (ie not contains mappedBy) unless you set both side.
          Reread the merge API you should do something like u1 = (U) em.merge(u); and work with u1.

          • 2. Re: ManyToMany: Howto use
            Darko Krizic Newbie

            Hi Emmanuell,

            it seems to work now. My entites are called "User" and "Group". It makes sence to explicitly define a different table name of hibernate will have problems with its SQL. Therefore I do

            @Entity
            @Table(name="xgroup")
            public class Group implements Serializable, Displayable {

            @ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST,
            CascadeType.MERGE }, mappedBy="users")
            @AssociationTable(table = @Table(name = "user_group"), joinColumns = { @JoinColumn(name = "user_id_ref", referencedColumnName = "user_id") }, inverseJoinColumns = { @JoinColumn(name = "group_id_ref", referencedColumnName = "group_id") })
            public Set<User> getUsers() {
            return users;
            }


            and


            @Entity
            @Table(name = "xuser")
            public class User implements Serializable, Displayable {

            @ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.REFRESH,
            CascadeType.MERGE })
            public Set<Group> getGroups() {
            return groups;
            }



            Note that I define the table name "user_group". After deployment I find:

            mysql> show tables;
            +-----------------+
            | Tables_in_jboss |
            +-----------------+
            | user_group |
            | xgroup |
            | xuser |
            | xuser_xgroup |
            +-----------------+


            And after running a JUnit-Test i find the data in the table xuser_xgroup:

            mysql> select * from user_group;
            Empty set (0.01 sec)

            mysql> select * from xuser_xgroup;
            +---------------+-----------------+
            | xuser_user_id | groups_group_id |
            +---------------+-----------------+
            | 100 | 51 |
            | 101 | 51 |
            | 101 | 52 |
            +---------------+-----------------+
            3 rows in set (0.01 sec)


            • 3. Re: ManyToMany: Howto use
              Darko Krizic Newbie

              One note: JBoss EJB 2.1 renames Tables of entities automagically if the conflict with a SQL keyword, like "user" -> "xuser" and "group" -> "xgroup"

              • 4. Re: ManyToMany: Howto use
                Emmanuel Bernard Master

                hum
                You should set the @AssociationTable on the owner side, ie the side not declaring the mappedBy. And the association table should be unique (ie not user_group and xuser_xgroup), otherwise it will be considered as 2 unrelated associations.

                • 5. Re: ManyToMany: Howto use
                  Darko Krizic Newbie

                  Hi Emanuell,

                  is it possible, that the owner-side of ManyToMany *must* be FetchType.EAGER?