Skip to content
Advertisement

JPA With composite key non standard

I’m trying to do a JPA mapping for an existing database. I can’t really change the existing structure.

I managed to make it works, but Intellij is telling me that some column doesn’t exist even if it works. So I don’t know if there’s a better way to do this or if it’s Intellij that doesn’t support all the use cases.

I simplified my mapping and table for the question. The 2 tables with primary composite keys are:

Table_A
some_id_a
some_seq_a

Table B
some_id_a
some_seq_a
some_seq_b

And my mapping is:

@Data
@Entity(name="Table_A")
public class TableA {
  @EmbeddedId
  private Key key;

  @OneToMany
  @JoinColumn(name = "someIdA")
  @JoinColumn(name = "someSeqA")
  private List<TableB> tableBs;

  @Data
  @Embeddable
  public static final class Key implements Serializable {
    private String someIdA;
    private long someSeqA;
  }
}

@Data
@Entity(name="Table_B")
public class TableB {
  @EmbeddedId
  private Key key;

  @Data
  @Embeddable
  public static final class Key implements Serializable {
    private String someIdA;
    private long someSeqA;
    private long someSeqB;
  }
}

So like I said it works but I have an error in Intellij saying that the @JoinColumn(name ="someIdA") @JoinColumn(name = "someSeqA") don’t exist and is expecting something like @JoinColumn(name ="some_id_a") @JoinColumn(name = "some_seq_a").

Using it the way Intellij is telling me, JPA has en error that says: Table [table_b] contains physical column name [some_id_a] referred to by multiple logical column names: [some_id_a], [someIdA].

My mapping is ok despite Intellij but is there’s a better alternative ?

Thanks

Advertisement

Answer

You can use a “derived identity” and map your classes like this:

@Data
@Entity(name="Table_A")
public class TableA {
  @EmbeddedId
  private Key key;

  @OneToMany(mappedBy = "tableA")
  private List<TableB> tableBs;

  @Data
  @Embeddable
  public static final class Key implements Serializable {
    private String someIdA;
    private long someSeqA;
  }
}


@Data
@Entity(name="Table_B")
public class TableB {
  @EmbeddedId
  private Key key;

  @MapsId("tableAKey") // maps tableAKey attribute of embedded id
  @JoinColumns({
    @JoinColumn(name="some_id_a", referencedColumnName="some_id_a"),
    @JoinColumn(name="some_seq_a", referencedColumnName="some_seq_a")
  })
  @ManyToOne
  private TableA tableA;

  @Data
  @Embeddable
  public static final class Key implements Serializable {
    private TableA.Key tableAKey; // corresponds to PK type of TableA
    private long someSeqB;
  }
}

Derived identities are discussed (with examples) in the JPA 2.2 spec in section 2.4.1.

Advertisement