7 Replies Latest reply on Mar 25, 2009 7:18 AM by mravikrish

    many to many mapping problem

    mravikrish


      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

          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

          • 2. Re: many to many mapping problem
            mravikrish

            Thanks Very Much problem was resolved

            • 3. Re: many to many mapping problem
              mravikrish

              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

                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
                  mravikrish

                  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
                    mravikrish


                    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
                      mravikrish

                      sorry
                      in persistence.xml i have configured property like this

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