如何在JPA中创建一个包含@ManyToOne属性的复合主键作为@EmbeddedId?

Tom*_*son 8 jpa composite-key many-to-one jpa-2.0

问并回答我自己的问题,但我不认为我有最好的答案.如果你有一个更好的,请发布它!

相关问题:

我有一对处于简单聚合关系的类:任何一个实例都拥有另一个实例.拥有类具有自己的某种主键,并且拥有的类通过相应的外键与该类具有多对一.我希望拥有的类具有包含该外键的主键以及一些附加信息.

为了争论,让我们使用那些常年的最爱,Order和OrderLine.

SQL看起来像这样:

-- 'order' may have been a poor choice of name, given that it's an SQL keyword!
create table Order_ (
    orderId integer primary key
);
create table OrderLine (
    orderId integer not null references Order_,
    lineNo integer not null,
    primary key (orderId, lineNo)
);
Run Code Online (Sandbox Code Playgroud)

我想使用JPA将其映射到Java.订单很简单,OrderLine可以用@IdClass处理.这是代码 - 代码相当传统,我希望你会原谅我的特质.

但是,使用@IdClass涉及编写ID类,该类复制OrderLine中的字段.我想避免重复,所以我想使用@EmbeddedId.

然而,一个天真的尝试这样做失败了:

@Embeddable
public class OrderLineKey {
    @ManyToOne
    private Order order;
    private int lineNo;
}
Run Code Online (Sandbox Code Playgroud)

OpenJPA拒绝将其用作@EmbeddedId.我没有尝试过其他提供程序,但我不希望它们成功,因为JPA规范要求构成ID类的字段是基本的,而不是关系.

那么,我该怎么办?我如何编写一个其键包含@ManyToOne关系的类,但是作为@EmbeddedId处理?

Tom*_*son 16

我不知道如何做到这一点,不涉及复制任何字段(抱歉!).但它可以通过简单而标准的方式完成,只涉及复制关系字段.关键是JPA 2中引入的@MapsId注释.

可嵌入的键类看起来像这样:

@Embeddable
public class OrderLineKey {
    private int orderId;
    private int lineNo;
}
Run Code Online (Sandbox Code Playgroud)

嵌入实体类看起来像这样:

@Entity
public class OrderLine{
    @EmbeddedId
    private OrderLineKey id;

    @ManyToOne
    @MapsId("orderId")
    private Order order;
}
Run Code Online (Sandbox Code Playgroud)

@MapsId注释声明应用它的关系字段有效地重新映射嵌入ID中的基本字段.

这是OrderId的代码.

  • 如果您要引用的实体具有复合键,该怎么办?您可以在嵌入式ID中的多个列上使用MapsId吗? (9认同)