使用复合键连接两个表

时间:2014-03-26 23:02:38

标签: java-ee jpa jpa-2.0

我把手放在一个非常古老的基于数据库的遗留应用程序(即MySQL)上,该应用程序有两个用于映射发票的表:让我们称之为INVOICE_HEADER和INVOICE_ROWS。

嗯,理想情况显然是 Invoice 实体中的@Id Long id;和双向@OnetoMany + @ManyToOne关系,由INVOICE_ROWS表中的FK_HEADER外键映射。正常的JPA方式来映射这种类型的关系。

然而,该表(标题一)具有四个(是,四个!)列作为复合主键(年,数字,t1,t2)以及行表。该应用程序正在使用这四列在两个表之间进行手动连接。 完全没有外键约束。

不幸的是,架构根本不可更改。 我将如何编写两个JPA实体? 我认为这是@IdClass(或@EmbeddedId?)的用例。

是否可以通过复合键映射@OneToMany关系? 你能帮我举几个例子吗?谢谢

1 个答案:

答案 0 :(得分:2)

是的,它是可能的,而且根本不应该是困难的 - JPA基于ORM的设计是灵活的解决方案。 JPA使用的ID甚至不必是数据库中使用的pk;唯一的限制是它应该是唯一的。 JPA 2包括对派生ID的支持,这可能有所帮助,因为我假设INVOICE_ROWS的pk是INVOICE_HEADER FK和其他一些字段的组合。如果它有自己的序列,那么它会简化它。

您可以选择要使用的选项--IdClass或将实体中的id类缓存为EmbeddedId。我的偏好通常是IdClass,因为我不太喜欢上课。所以一个简单的例子就是:

@Entity
@IdClass(HeaderPK.class)
class Header {
  @Id
  java.sql.Date year;
  @Id
  Integer number;
  @Id
  String t1;
  @Id
  String t2;
  @OneToMany(mappedby="header")
  List<Row> rows;
}

class HeaderPK {
  java.sql.Date year;
  Integer number;
  String t1;
  String t2;
}

@Entity
@IdClass(RowPK.class)
class Row {
  @Id
  String someField;
  @Id
  @ManyToOne
  @JoinColumns({
      @JoinColumn(name="YEAR", referencedColumnName="YEAR"),
      @JoinColumn(name="NUMBER", referencedColumnName="NUMBER"),
      @JoinColumn(name="T1", referencedColumnName="T1"),
      @JoinColumn(name="T2", referencedColumnName="T2"),
  })
  Header header;
}

class RowPK {
  String someField;
  HeaderPK header;
}

每个JoinColumn注释都定义外键字段以及它们指向的主键字段。 JPA有一个限制,即外键必须转到主键字段 - 我相信这是允许实体缓存,因为它们缓存在主键上。如果需要,许多提供商可以解决此限制。

如果您的Row实体只有一个主键,则可以使用RowPk类。