Composite Primary Key with @ManyToOne

Here is a fun issue that I ran into the other day while working with a legacy database.

Three tables:

Nodes

  • NodeID(pk)

Interfaces

  • InterfaceID(pk)

  • NodeID(fk)

InterfaceTraffic_Detail

  • InterfaceID(pk)

  • DateTime(pk)

  • NodeID(fk)

The InterfaceTraffic_Detail table turned out to be a little tricky for me since I have never worked with composite indexes in hibernate. It took a little trial and error but here is what I came up with

My environment is Hibernate 3.4

NmsNode.java

@Name("nmsNode")
@Entity
@Table(name="Nodes")
public class NmsNode implements Serializable {
  private static final long serialVersionUID = 1462044144509159489L;

  private int id;
  private List<NmsInterface> interfaces;

  @Id
  @Column(name="NodeID")
  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  @OneToMany(mappedBy="node", fetch=FetchType.LAZY)
  public List<NmsInterface> getInterfaces() {
    return interfaces;
  }

  public void setInterfaces(List<NmsInterface> interfaces) {
    this.interfaces = interfaces;
  }
}

NmsInterface.java

@Name("nmsInterface")
@Entity
@Table(name="Interfaces")
public class NmsInterface implements Serializable
{

   private static final long serialVersionUID = 1L;

   private int id;
   private NmsNode node;


   @Id
   @Column(name="InterfaceID")
   public int getId()
   {
      return id;
   }
   public void setId(int id)
   {
      this.id = id;
   }

   @ManyToOne
   @JoinColumn(name="NodeID")
   public NmsNode getNode()
   {
      return node;
   }
   public void setNode(NmsNode node)
   {
      this.node = node;
   }
}

InterfaceTraffic_Detail.java

@Entity
@Table(name="InterfaceTraffic_Detail")
@AssociationOverrides
   (
      {
           @AssociationOverride(name = "id.nmsInterface",
                 joinColumns = @JoinColumn(name = "InterfaceID"))
      }
   )
public class InterfaceTraffic_Detail implements Serializable
{
   private static final long serialVersionUID = 1L;
   private InterfaceTraffic_PrimaryKey id;
   private NmsNode nmsNode;

   @EmbeddedId
   @AttributeOverrides
   (
         {
            @AttributeOverride(name="id.dateTime", column=@Column(name="DateTime"))
         }
   )
   public InterfaceTraffic_PrimaryKey getId()
   {
      return id;
   }
   public void setId(InterfaceTraffic_PrimaryKey id)
   {
      this.id = id;
   }
   @ManyToOne
   @JoinColumn(name="NodeID")
   public NmsNode getNmsNode()
   {
      return nmsNode;
   }
   public void setNmsNode(NmsNode nmsNode)
   {
      this.nmsNode = nmsNode;
   }
}

InterfaceTraffic_PrimaryKey.java

@Embeddable
public class InterfaceTraffic_PrimaryKey implements Serializable
{
   private static final long serialVersionUID = 1L;
   private NmsInterface nmsInterface;
   private Date dateTime;

   @ManyToOne
   public NmsInterface getNmsInterface()
   {
      return nmsInterface;
   }
   public void setNmsInterface(NmsInterface nmsInterface)
   {
      this.nmsInterface = nmsInterface;
   }
   public Date getDateTime()
   {
      return dateTime;
   }
   public void setDateTime(Date dateTime)
   {
      this.dateTime = dateTime;
   }

   public int hashCode() {
      return (int) dateTime.hashCode() + nmsInterface.getId();
  }

  public boolean equals(Object obj) {
      if (obj == this) return true;
      if (obj == null) return false;
      if (!(obj instanceof InterfaceTraffic_PrimaryKey)) return false;
      InterfaceTraffic_PrimaryKey pk = (InterfaceTraffic_PrimaryKey) obj;
      return pk.nmsInterface.getId() == nmsInterface.getId() && pk.dateTime.equals(dateTime);
  }
}

The important part here is the @EmbeddedId and @Embeddable on the InterfaceTraffic_Detail and InterfaceTraffic_PrimaryKey as well as the name "id.nmsInterface" on the @AssociationOverride so that I could reference the variable on the embedded class and define the @JoinColumn

Hopefully this saves someone else some time.

tags: java hibernate
Cody Lerum - January 12, 2010
About outjected.com

Outjected is an infrequent blog about the frequent issues and annoyances that pop up while coding.

These are living posts and will be updated as errors or improvements are found.
About Me
Google+