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

发布于 2024-12-01 23:20:51 字数 1604 浏览 3 评论 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)
);

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

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

然而,天真的尝试会失败:

@Embeddable
public class OrderLineKey {
    @ManyToOne
    private Order order;
    private int lineNo;
}

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

那么,我能做什么呢?我如何编写一个类,其键包含@ManyToOne关系,但作为@EmbeddedId处理?

I'm asking and answering my own question, but i'm not assuming i have the best answer. If you have a better one, please post it!

Related questions:

I have a pair of classes which are in a simple aggregation relationship: any instance of one owns some number of instances of the other. The owning class has some sort of primary key of its own, and the owned class has a many-to-one to this class via a corresponding foreign key. I would like the owned class to have a primary key comprising that foreign key plus some additional information.

For the sake of argument, let's use those perennial favourites, Order and OrderLine.

The SQL looks something like this:

-- '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)
);

I would like to map this into Java using JPA. Order is trivial, and OrderLine can be handled with an @IdClass. Here's the code for that - the code is fairly conventional, and i hope you'll forgive my idiosyncrasies.

However, using @IdClass involves writing an ID class which duplicates the fields in the OrderLine. I would like to avoid that duplication, so i would like to use @EmbeddedId instead.

However, a naive attempt to do this fails:

@Embeddable
public class OrderLineKey {
    @ManyToOne
    private Order order;
    private int lineNo;
}

OpenJPA rejects the use of that as an @EmbeddedId. I haven't tried other providers, but i wouldn't expect them to succeed, because the JPA specification requires that the fields making up an ID class be basic, not relationships.

So, what can i do? How can i write a class whose key contains @ManyToOne relationship, but is handled as an @EmbeddedId?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你如我软肋 2024-12-08 23:20:51

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

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

@Embeddable
public class OrderLineKey {
    private int orderId;
    private int lineNo;
}

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

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

    @ManyToOne
    @MapsId("orderId")
    private Order order;
}

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

这是 OrderId 的代码

I don't know of a way to do this which doesn't involve duplicating any fields (sorry!). But it can be done in a straightforward and standard way that involves duplicating only the relationship fields. The key is the @MapsId annotation introduced in JPA 2.

The embeddable key class looks like this:

@Embeddable
public class OrderLineKey {
    private int orderId;
    private int lineNo;
}

And the embedding entity class looks like this:

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

    @ManyToOne
    @MapsId("orderId")
    private Order order;
}

The @MapsId annotation declares that the relationship field to which it is applied effectively re-maps a basic field from the embedded ID.

Here's the code for OrderId.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文