2 Replies Latest reply on Jul 4, 2007 9:46 PM by waynebaylor

    EJB 3 OneToMany with Composite Key

    deanouk

      Hi all,

      Having a problem setting up my first EJB 3 OneToMany relationship with a composite key.

      Here's the error:
      14:09:01,812 WARN [JDBCExceptionReporter] SQL Error: 957, SQLState: 42000
      14:09:01,812 ERROR [JDBCExceptionReporter] ORA-00957: duplicate column name

      The 'One' Entity:

      
      
      import javax.persistence.*;
      import java.io.Serializable;
      import java.util.Collection;
      
      
      
      @Entity
      @Table(name = "COMMS_MESSAGES")
      public class CommsMessage implements Serializable
      {
      
       private int messageId;
      
       /**
       * Any attachments.
       */
       private Collection<CommsAttachment> commsAttachments;
      
      
       public CommsMessage()
       {
       }
      
      
       @Id
       @GeneratedValue(strategy = GenerationType.AUTO)
       public int getMessageId()
       {
       return messageId;
       }
      
       public void setMessageId(int messageId)
       {
       this.messageId = messageId;
       }
      
       @OneToMany(mappedBy = "commsMessage", cascade = {CascadeType.PERSIST, CascadeType.REMOVE}, fetch=FetchType.LAZY)
       public Collection<CommsAttachment> getCommsAttachments()
       {
       return commsAttachments;
       }
      
       public void setCommsAttachments(Collection<CommsAttachment> commsAttachments)
       {
       this.commsAttachments = commsAttachments;
       }
      
      
      
      }
      
      

      The 'Many' Entity:
      
      
      import javax.persistence.*;
      import java.io.Serializable;
      
      /**
       * Comms Message Entity Bean
       *
       * @author Dean Pullen
       * @since 03-Jul-2007
       */
      @Entity
      @Table(name = "COMMS_MESSAGE_RECIPIENTS")
      @IdClass(CommsMessageRecipientPK.class)
      public class CommsMessageRecipient implements Serializable
      {
       private CommsMessage commsMessage;
      
       private int messageId;
      
       private int recipientUserId;
      
      
       public CommsMessageRecipient()
       {
       }
      
       @ManyToOne
       @JoinColumn(name = "messageid")
       public CommsMessage getCommsMessage()
       {
       return commsMessage;
       }
      
       public void setCommsMessage(CommsMessage commsMessage)
       {
       this.commsMessage = commsMessage;
       }
      
       @Id
       public int getMessageId()
       {
       return messageId;
       }
      
       public void setMessageId(int messageId)
       {
       this.messageId = messageId;
       }
      
       @Id
       public int getRecipientUserId()
       {
       return recipientUserId;
       }
      
       public void setRecipientUserId(int recipientUserId)
       {
       this.recipientUserId = recipientUserId;
       }
      }
      
      

      The Composite Key:
      package com.msp.ejb.lms.comms;
      
      import java.io.Serializable;
      
      public class CommsMessageRecipientPK implements Serializable
      {
       private int messageId;
      
       private int recipientUserId;
      
      
       public CommsMessageRecipientPK()
       {
       }
      
       public CommsMessageRecipientPK(int messageId, int recipientUserId)
       {
       this.messageId = messageId;
       this.recipientUserId = recipientUserId;
       }
      
      
       public int getMessageId()
       {
       return messageId;
       }
      
       public void setMessageId(int messageId)
       {
       this.messageId = messageId;
       }
      
       public int getRecipientUserId()
       {
       return recipientUserId;
       }
      
       public void setRecipientUserId(int recipientUserId)
       {
       this.recipientUserId = recipientUserId;
       }
      
      
       public boolean equals(Object o)
       {
       if (this == o) return true;
       if (o == null || getClass() != o.getClass()) return false;
      
       CommsMessageRecipientPK that = (CommsMessageRecipientPK) o;
      
       return messageId == that.messageId && recipientUserId == that.recipientUserId;
      
       }
      
       public int hashCode()
       {
       int result;
       result = messageId;
       result = 31 * result + recipientUserId;
       return result;
       }
      }
      
      



      As you can see, I'm trying to map the CommsMessage to multiple CommsRecipients using the 'messageid' value found in both tables.

      Any help greatly appreciated.

        • 1. Re: EJB 3 OneToMany with Composite Key
          deanouk

          That first set of code should have:

          @OneToMany(mappedBy = "commsMessage", cascade = {CascadeType.PERSIST, CascadeType.REMOVE}, fetch=FetchType.LAZY)
           public Collection<CommsMessageRecipient> getCommsMessageRecipients()
           {
           return commsMessageRecipients;
           }
          
           public void setCommsMessageRecipients(Collection<CommsMessageRecipient> commsMessageRecipients)
           {
           this.commsMessageRecipients = commsMessageRecipients;
           }
          


          Ignore the CommsAttachment object - thats meant to be having the same relationship but I took it out for this example.

          • 2. Re: EJB 3 OneToMany with Composite Key
            waynebaylor

            if i remember correctly, the @OneToMany relationship will, by default, create a table for the "many" side which will contain a foreign key referencing the "one" side.

            so, since messageId is the PK for CommsMessage the table representing CommsMessageRecipient will have two columns named messageId: one as the FK referencing CommsMessge and another as part of its own PK.