1 2 Previous Next 17 Replies Latest reply on Sep 19, 2005 1:28 PM by dornus

    Help setting up entity bean with complex PK

    dornus Novice

      I have just gone through the demos and trails and cannot find anything explaining the way to correctly setup a compound primary key for this particular situation. Below is a simple example of what I am trying to do.

      I have 2 tables, (user and blocklist). The primary key of the user table is userId. The compound primary key of the blocklist is ownerId and blockedId. Both ownerId and blockedId are foreign keys which reference userId. This is shown below:

      Table 1 - "user"
      userId - Primary Key (int - autogenerated by database)
      firstName varchar(30)


      Table 2 - "blocklist"
      ownerId (FK mapped to userId of table 'user')
      blockedId (FK mapped to userId of table 'user')
      timestamp (created when a record is inserted)

      I am guessing this is a many-to-many relationship. This is based on the fact that:
      - An ownerId can have multiple blockedIds.
      - A blockedId can appear for multiple ownerIds.

      This is what I have coded so far. I keep getting errors (which I assume have to do with the mappings). Where am I going wrong?


      ###############
      # User Entity Bean
      ###############
      @Entity
      @Table(name = "user")
      public class User {
      @Id(generate = GeneratorType.AUTO)
      @Column(name = "userId")
      public long getUserId() {
      return userId;
      }
      //etc...
      }


      ###############
      # Blocklist Entity Bean
      ###############
      @Entity
      @Table(name = "blocklist")
      public class Blocklist implements Serializable {

      private BlocklistPK blocklistPK;
      private Timestamp date;

      @EmbeddedId
      public BlocklistPK getBlocklistPK() {
      return blocklistPK;
      }
      //etc...
      }

      ###############
      # Blocklist Compund PK
      ###############
      @Embeddable
      public class BlocklistPK implements Serializable {

      private User ownerId;
      private User blockedId;

      @ManyToMany
      @JoinColumn(name="ownerId",nullable=false)
      public User getOwnerId(){
      return ownerId;
      }


      @ManyToMany
      @JoinColumn(name="blockedId",nullable=false)
      public User getBlockedId(){
      return blockedId;
      }

      public int hashCode(){
      return ownerId.hashCode() + blockedId.hashCode();
      }

      public boolean equals(Object obj){
      if (obj == null){
      return false;
      }
      else if (obj == this){
      return true;
      }
      else if (!(obj instanceof BlocklistPK)){
      return false;
      }

      BlocklistPK pk = (BlocklistPK) obj;
      return pk.ownerId.equals(ownerId) && pk.blockedId.equals(blockedId);
      }

      //etc...
      }

      ############

      I have gotten such errors as:
      org.hibernate.MappingException: Could not determine type for: par.User, for columns: [org.hibernate.mapping.Column(userId)]
      and
      org.hibernate.AnnotationException: par.User collection not yet supported: par.BlocklistPKownerId
      and
      java.util.NoSuchElementException
      and
      java.lang.NullPointerException

      These errors depend on if I set the BlocklistPK columns to OneToOne,OneToMany,ManyToOne or ManyToMany

      Can anyone help me figure out what I am doing wrong?

      Thanks!

        • 1. Re: Help setting up entity bean with complex PK
          dornus Novice

          Sorry, here is the same message with code formatting.
          ---------------------------------------------------------------

          I have just gone through the demos and trails and cannot find anything explaining the way to correctly setup a compound primary key for this particular situation. Below is a simple example of what I am trying to do.

          I have 2 tables, (user and blocklist). The primary key of the user table is userId. The compound primary key of the blocklist is ownerId and blockedId. Both ownerId and blockedId are foreign keys which reference userId. This is shown below:

          Table 1 - "user"
          userId - Primary Key (int - autogenerated by database)
          firstName varchar(30)


          Table 2 - "blocklist"
          ownerId (FK mapped to userId of table 'user')
          blockedId (FK mapped to userId of table 'user')
          timestamp (created when a record is inserted)

          I am guessing this is a many-to-many relationship. This is based on the fact that:
          - An ownerId can have multiple blockedIds.
          - A blockedId can appear for multiple ownerIds.

          This is what I have coded so far. I keep getting errors (which I assume have to do with the mappings). Where am I going wrong?


          ###############
          # User Entity Bean
          ###############

          @Entity
          @Table(name = "user")
          public class User {
           @Id(generate = GeneratorType.AUTO)
           @Column(name = "userId")
           public long getUserId() {
           return userId;
           }
           //etc...
          }
          


          ###############
          # Blocklist Entity Bean
          ###############
          @Entity
          @Table(name = "blocklist")
          public class Blocklist implements Serializable {
          
           private BlocklistPK blocklistPK;
           private Timestamp date;
          
           @EmbeddedId
           public BlocklistPK getBlocklistPK() {
           return blocklistPK;
           }
           //etc...
          }
          


          ###############
          # Blocklist Compund PK
          ###############
          @Embeddable
          public class BlocklistPK implements Serializable {
          
           private User ownerId;
           private User blockedId;
          
           @ManyToMany
           @JoinColumn(name="ownerId",nullable=false)
           public User getOwnerId(){
           return ownerId;
           }
          
          
           @ManyToMany
           @JoinColumn(name="blockedId",nullable=false)
           public User getBlockedId(){
           return blockedId;
           }
          
           public int hashCode(){
           return ownerId.hashCode() + blockedId.hashCode();
           }
          
           public boolean equals(Object obj){
           if (obj == null){
           return false;
           }
           else if (obj == this){
           return true;
           }
           else if (!(obj instanceof BlocklistPK)){
           return false;
           }
          
           BlocklistPK pk = (BlocklistPK) obj;
           return pk.ownerId.equals(ownerId) && pk.blockedId.equals(blockedId);
           }
          
           //etc...
          }
          

          ############

          I have gotten such errors as:
          org.hibernate.MappingException: Could not determine type for: par.User, for columns: [org.hibernate.mapping.Column(userId)]
          and
          org.hibernate.AnnotationException: par.User collection not yet supported: par.BlocklistPKownerId
          and
          java.util.NoSuchElementException
          and
          java.lang.NullPointerException

          These errors depend on if I set the BlocklistPK columns to OneToOne,OneToMany,ManyToOne or ManyToMany

          Can anyone help me figure out what I am doing wrong?

          Thanks!


          • 2. Re: Help setting up entity bean with complex PK
            Emmanuel Bernard Master

            as per the doc @*ToOne and @*ToMany are not supported in embeddable objects

            • 3. Re: Help setting up entity bean with complex PK
              dornus Novice

               

              "epbernard" wrote:
              as per the doc @*ToOne and @*ToMany are not supported in embeddable objects


              So how would this be achieved then? What is the workaround?


              Thanks.

              • 4. Re: Help setting up entity bean with complex PK
                dornus Novice

                 

                "epbernard" wrote:
                as per the doc @*ToOne and @*ToMany are not supported in embeddable objects


                I assume you are talking about this? Last sentence of last paragraph of Section 2.2.2.3

                http://www.hibernate.org/hib_docs/annotations/reference/en/html_single/

                "Overriding columns of embedded objects of embedded objects is currently not supported in the EJB3 spec."

                If so is there a workaround, or an estimated release date for added support?


                • 5. Re: Help setting up entity bean with complex PK
                  Emmanuel Bernard Master

                  Hum, it's actually not written,
                  Embeddable objects does not allows associations. I don't have any timeframe for that one

                  For the sentence you are refering to, it's fixed in CVS.

                  • 6. Re: Help setting up entity bean with complex PK
                    dornus Novice

                     

                    "epbernard" wrote:
                    Hum, it's actually not written,
                    Embeddable objects does not allows associations. I don't have any timeframe for that one

                    For the sentence you are refering to, it's fixed in CVS.


                    Is there any workaround that can be done? This greatly hinders my use of ejb3 as it is unusable for my application due to this situation. It seems pretty common for people to have compound keys comprised of foreign keys.

                    Thank you

                    • 8. Re: Help setting up entity bean with complex PK
                      Emmanuel Bernard Master

                      See the Hibernate Annotations 3.1beta5 doc, there is a workaround sample

                      • 9. Re: Help setting up entity bean with complex PK
                        dornus Novice

                         

                        "epbernard" wrote:
                        See the Hibernate Annotations 3.1beta5 doc, there is a workaround sample


                        Do you have a url for that? I could only find one for beta4 at

                        http://www.hibernate.org/5.html


                        Thanks

                        • 10. Re: Help setting up entity bean with complex PK
                          dornus Novice

                           

                          "Dornus" wrote:
                          "epbernard" wrote:
                          See the Hibernate Annotations 3.1beta5 doc, there is a workaround sample


                          I downloaded the beta5 release and unzipped it and it seems that the documentation is there, but I do not see the workaround sample that you are referring to. Do you know what file or chapter it is in, or what the sample is about?

                          Thank you


                          • 11. Re: Help setting up entity bean with complex PK
                            Emmanuel Bernard Master

                            My bad, I did document something else. Sorry.

                            The solution is to map the PK using a regular property
                            and them map a @ManyToOne on the same column but outside the composite key. The columns has to be set updatable, insertable = false

                            @ManyToOne
                            @JoinColumn(name='samecolumnnameasthecompositeproperty", insertable=false, updatable=false)
                            public MyOhterEntity

                            • 12. Re: Help setting up entity bean with complex PK
                              dornus Novice

                               

                              "epbernard" wrote:
                              My bad, I did document something else. Sorry.

                              The solution is to map the PK using a regular property
                              and them map a @ManyToOne on the same column but outside the composite key. The columns has to be set updatable, insertable = false

                              @ManyToOne
                              @JoinColumn(name='samecolumnnameasthecompositeproperty", insertable=false, updatable=false)
                              public MyOhterEntity


                              I'm having a little trouble understanding the solution.

                              If I have 2 classes
                              MyClass{
                               MyClassPK pKey;
                              }
                              
                              MyClassPK{
                               MyForeignClassA classA;
                               MyForeignClassB classB;
                              }
                              

                              are you saying to do this?

                              MyClass{
                               MyClassPK pKey;
                              
                               @ManyToOne
                               @JoinColumn(name='classA", insertable=false, updatable=false)
                               MyForeignClassA classA;
                              
                               @ManyToOne
                               @JoinColumn(name='classB", insertable=false, updatable=false)
                               MyForeignClassB classB;
                              }
                              
                              MyClassPK{
                              //Assume that in the database these are foreign keys
                              //which are int values. So instead of the class they
                              //represent (MyForeignClassA, MyForeignClassB), just
                              //use the int value instead.
                               int classA;
                               int classB;
                              }
                              



                              1 2 Previous Next