JPA Overlapping complex keys

I have one app that has a table with 2 complex-key relationships. The table’s primary key is (idA, idB) and there’s a foreign key reference to another table item with a key of (idA, idC). The table’s key is an embedded object of type “table1Id” and the foreign reference is a lazy-load “table2” object.

The most important thing to realize is that in JPA, each of the jpa-mapped columns must have a corresponding JPA property. The primary key is an embedded object, so its columns are defined within that object. Then the actual Entity object employs it like so:

@EmbeddedId
@AttributeOverrides( {
  @AttributeOverride(name = "idA", column = @Column(name = "ID_A", nullable = false)),
  @AttributeOverride(name = "idB", column = @Column(name = "ID_B", nullable = false, precision = 5, scale = 0)) })
public AObjectId getId() {
  return this.id;
}

The foreign object reference is a bit trickier. If you just point to the foreign object, you won’t actually define the “idC” part of the key within the referencing entity and Hibernate won’t generate SQL for it. Which can make inserts fail, if the foreign reference is mandatory, and can generally be counted on to cause mischief.

So, to make the basic foreign reference, the code goes like this:

@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.MERGE,optional=false)
@JoinColumns( {
  @JoinColumn(name = "ID_A", nullable = false, insertable = false, updatable = false),
  @JoinColumn(name = "ID_C", nullable = false, insertable = false, updatable = false) })
public CObject getCObject() {
  return this.cObject;
}

However, to make the reference WORK, you also need to define a property in your referencing entity for the “ID_C” column to be held in.

private int idC;

@Column(name="ID_C")
public int getIdC() {
  return this.idC;
}

public void setIdC(int value) {
  this.idC = value;
}

Note that in the compound references, the columns are required to be non-insertable, non-updateable. That’s because the primary objects are the updateable ones. Attempting otherwise will generally get you yelled at by JPA.

Also, I’ve discovered that in Hibernate, at least, setting up a reference to a “CObject” is not sufficient. I also have to set idC equal to the idc value of the CObject’s primary key or the insert value for that column will be incorrect (since it’s the updateable propery). ORM frameworks will often let you get by with not setting all the cross-connections in an object relationship, but since they generally don’t do sanity checks on such things, you can end up with unexpected behaviors if you don’t.