我把手放在一个非常古老的基于数据库的遗留应用程序(即MySQL)上,该应用程序有两个用于映射发票的表:让我们称之为INVOICE_HEADER和INVOICE_ROWS。
嗯,理想情况显然是 Invoice 实体中的@Id Long id;
和双向@OnetoMany + @ManyToOne关系,由INVOICE_ROWS表中的FK_HEADER外键映射。正常的JPA方式来映射这种类型的关系。
然而,该表(标题一)具有四个(是,四个!)列作为复合主键(年,数字,t1,t2)以及行表。该应用程序正在使用这四列在两个表之间进行手动连接。 完全没有外键约束。
不幸的是,架构根本不可更改。 我将如何编写两个JPA实体? 我认为这是@IdClass(或@EmbeddedId?)的用例。
是否可以通过复合键映射@OneToMany关系? 你能帮我举几个例子吗?谢谢
答案 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类。