7 Replies Latest reply on Mar 25, 2009 7:18 AM by ravi krishna muthireddy

    many to many mapping problem

    ravi krishna muthireddy Newbie


      Hi,

      This is Ramu, i am having a problem with many to many mapping. i am havig two tables vendor and skills(many - to many).

      Vendor pojo class:
      private Collection skills = new ArrayList();

      @ManyToMany()
      @JoinTable(name = "VENDORSKILLS")
      getter and setter follows............
      .........................

      Skill pojo class

      private Collection vendors = new ArrayList();

      @ManyToMany(mappedBy="skills",cascade={CascadeType.ALL})
      getter and setter follows............
      .........................

      Now join table VENDORSKILLS is having colums like vendor_Id and skill_Id

      Now I want to have one extra column like skilllevel .How to create skilllevel column in join table VENDORSKILLS .

      And how to persist it.

      Thanks&Regards
      K.Ramu




        • 1. Re: many to many mapping problem
          Jochen Reinhardt Newbie

          Hi Ramu,

          I suggest the following solution:
          Split up your m:n relation into one additional entity and two 1:n relations.
          Your additional entity could be named SkillLevel or something like that.

          It's properties:
          int SkillLevel

          It has the following relations:
          ManyToOne to Vendor
          ManyToOne to Skill

          The primary key must be a compound key -> skill, vendor.
          Use an @Embeddable key class with @EmbeddedId that references these entities with their primary key.

          Should look something like this: Please annotate the getters in your code...

          @Entity
          public class Vendor implements Serializable
          {
           @Id
           int id;
           @OneToMany(mappedBy="vendor")
           List<SkillLevel> skills;
           //...
          }
          
          @Entity
          public class Skill implements Serializable
          {
           @Id
           int id;
           @OneToMany(mappedBy="skill")
           List<SkillLevel> skills;
           //...
          }
          
          @Entity
          public class SkillLevel implements Serializable
          {
           @EmbeddedId
           SkillLevelKey key;
           int level;
          
           @ManyToOne
           Skill skill;
          
           @ManyToOne
           Vendor vendor;
          
           @Embeddable
           public static final class SkillLevelKey implements Serializable
           {
           int skill;
           int vendor;
           // must define equals() and hashCode()
           }
          }
          


          Hope that helps!

          Cheers,
          Jochen

          • 3. Re: many to many mapping problem
            ravi krishna muthireddy Newbie

            But i am getting exception while saving SkillLevel object
            The Exception is as follows

            org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): com.connectvendors.ejb.entity.SkillLevel

            • 4. Re: many to many mapping problem
              Jochen Reinhardt Newbie

              The messages indicate, that you do not have your primary key set correctly. I think you have to do that manually. It's a bit tricky, as your primary key for skill level is a composition of two foreign keys. I think you have to correct that...

              I solved the problem by adding @Column (in the primary key class) and @JoinColumn (for your releationships) and @AttributeOverride (for your embedded primary key) annotation. For the JoinColumn, I had to set insertable and updateable to false, as the columns will be generated by the primary key. Use the same names for the columns in your primary key class as for the JoinColumns. I guess hibernate will have created distinct columns for your primary key and your relationship definition, but that's not what you really wanted. Check your schema to see what hibernat actually does on database level!

              Before saving your entities, be sure to set all fields of your bean. The primary key AND your relation fields - this feels like doing a little bit of work twice, but I think it turns out to be correct.

              For your relationships, try to find the correct settings for cascading. E.g, when you remove a vendor, you will also want that all skill levels for that vendor be removed. When you remove a skill, you may want that all skill levels be removed. Either use cascading or do it manually in your code.

              Good luck!
              Jochen






              • 5. Re: many to many mapping problem
                ravi krishna muthireddy Newbie

                Hi jochen,

                I am getting same exception . i have followed exactly what u have suggested. i am giving my persistence.xml


                <persistence-unit name="bids">
                <jta-data-source>java:/ConnectVendorsMySQL</jta-data-source>



                </persistence-unit>



                And SkillLevel class

                SkillLevelKey primaryKey;

                @EmbeddedId
                @AttributeOverrides({
                @AttributeOverride(name = "skill_Id", column = @Column(name = "skill_Id")),
                @AttributeOverride(name = "vendor_Id", column = @Column(name = "vendor_Id"))
                })

                getters and setters for primaryKey.

                lease tell me where i am doing mistake

                Thanks&Regards
                K.Ramu

                • 6. Re: many to many mapping problem
                  ravi krishna muthireddy Newbie


                  sorry persistence.xml file


                  <persistence-unit name="bids">
                  <jta-data-source>java:/ConnectVendorsMySQL</jta-data-source>



                  </persistence-unit>

                  • 7. Re: many to many mapping problem
                    ravi krishna muthireddy Newbie

                    sorry
                    in persistence.xml i have configured property like this

                    property name="hibernate.hbm2ddl.auto" value="update"