2014-03-26 72 views
0

我把手放在一个非常古老的基于数据库的旧应用程序(即MySQL)上,该应用程序有两张用于映射发票的表格:我们称之为INVOICE_HEADER和INVOICE_ROWS。使用复合键连接两个表

那么,理想的情况显然是在发票实体@Id Long id;和双向@OneToMany + @ManyToOne关系,通过在INVOICE_ROWS表FK_HEADER外键映射。正常的JPA方法来映射这种类型的关系。

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

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

是否可以通过组合键映射@OneToMany关系? 你能帮我一些例子吗?谢谢

回答

1

是的,这是可能的,应该不会有任何困难 - ORA JPA是基于设计灵活的解决方案。 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类来实现。