Joining Hibernate Entities with a UK on Part of a Composite Primary Key

543 Views Asked by At

I am using Hibernate 4.3 and am trying to model the relationship within the entities of a legacy database that cannot be changed.

I am trying to map a many-to-one relationship between Table B and Table A. Table A has a composite primary key made up of 3 columns. One of these columns is a unique key in and of itself (and has a unique constraint on it). Table B also has a composite primary key. One field of the composite PK for Table B is the FK to Table A using that unique value. Regardless of my attempts to map this relationship I usually get an error message by Hibernate.

Here's are the entities with fields not pertaining to this question removed for brevity:

@Embeddable
class APk {
   private int site;
   private int client;
   private int id;

  @Column(name = "site", nullable = false)
  public int getSite() { return this.site; }

  @Column(name = "client", nullable = false)
  public int getClient() { return this.client; } 

  @Id
  @Column(name = "id", nullable = false)
  public int getId() { return this.id; }
}

@Entity
@Table(name = "A", uniqueConstraints = { @UniqueConstraint(columnNames = "id") })
class A {
  private APk id;
  private String otherStuff;

  @EmbeddedId
  public APk getAPk() { return this.id; }
}

@Embeddable
class BPk {
   private String value;
   private int aId;

   @Column(name = "VALUE", nullable = false)
   public String getValue() { return this.value; }

   @Column(name = "A_ID", nullable = false)
   public int getAId() { return this.aId; }
}

@Entity
@Table(name = "B")
class B {
  private BPk id;
  private String moreFields;
  private A entityA;

  @EmbeddedId
  public BPk getId() { return this.id; }

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "a_id", referencedColumnName = "id", insertable = false, updatable = false)
  public A getEntityA() { return this.entityA; }
}

I have attempted to use @JoinColumn with that single field, but am given one of the two error messages:

  1. In the code above the error is

    referencedColumnNames(ID) of B referencing A not mapped to a single property

  2. If I remove the referencedColumnName property and add a @MapsId("id") annotation I get the error:

    org.hibernate.AnnotationException: A Foreign key refering A from B has the wrong number of column. should be 3

A few things to note:

  • Only B needs to be able to load A, the reverse is not required since it'll never be used. This hasn't seemed to simplify the mapping though.
  • I don't think I'm using the @MapsId annotation properly when removing the referencedColumnName property from the @JoinColumn annotation
  • Although it probably doesn't matter the underlying db is [unfortunately] Oracle 11g
  • I have seen other questions on SO similar to this one where we're attempting to reference a partial composite key, but none of them were able to answer this question since they either had those columns available in the database to update their model with, or the composite PK did not have a unique constraint on one of the columns.

Is there a way to handle this in Hibernate (4)? Would @JoinFormula be required for this kind of non-standard relationship?

EDIT: Some other things I have tried, but has not worked:

  • Replacing the @Embeddable/@EmbeddedId annotations with @IdClass annotations
  • Using @JoinColumnsOrFormulas annotation with formulas for the 2 "missing" fields that are not available in entity B, but are part of entity A's PK.
0

There are 0 best solutions below