如何在 JPA 中创建包含 @ManyToOne 属性作为 @EmbeddedId 的复合主键?
我我自己提问并回答问题,但我并不认为我有最好的答案。如果您有更好的,请发布!
相关问题:
我有一对处于简单聚合关系的类:其中一个的任何实例拥有对方的一定数量的实例。拥有类有自己的某种主键,并且拥有类通过相应的外键与该类具有多对一关系。我希望拥有的类有一个由该外键和一些附加信息组成的主键。
为了便于讨论,让我们使用那些长期最受欢迎的 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:
- How to set a backreference from an @EmbeddedId in JPA
- hibernate mapping where embeddedid (?)
- JPA Compound key with @EmbeddedId
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不知道有什么方法可以做到这一点,而不涉及复制任何字段(抱歉!)。但它可以通过一种简单且标准的方式来完成,只需复制关系字段。关键是 JPA 2 中引入的 @MapsId 注解。
可嵌入的关键类看起来像这样:
嵌入实体类看起来像这样:
@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:
And the embedding entity class looks like this:
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.