JPA 复合键@OneToMany

发布于 2024-12-06 15:01:27 字数 1396 浏览 0 评论 0原文

我有以下现有的数据库模式,我想使用 Java 和普通 JPA 注释重新创建它(使用 hibernate 作为提供程序,因此 hibernate 特定注释将作为最后的手段):

CREATE TABLE users (
    user_id NUMBER NOT NULL                     -- pk
);

CREATE TABLE userdata_keys (
    userdata_key_id NUMBER NOT NULL,            -- pk
    key VARCHAR2(128) NOT NULL                  
);

CREATE TABLE users_userdata (
    user_id NUMBER NOT NULL,                    -- fk users.user_id
    userdata_key_id NUMBER NOT NULL,            -- fk userdata_keys.userdata_key_id 
    value VARCHAR2(256)                         
);

因此,我创建了以下类和注释:

class User {
    @Id
    Long id;
    @OneToMany
    Set<Userdata> userdata;
}

class UserdataKey {
    @Id
    Long id;
    String key;
}

class Userdata {
    String value;
    @EmbeddedId
    UserdataId userdataId;
}

@Embeddable
class UserdataId {
    User user;
    UserdataKey userdataKey;
}

我在这里省略了实体的 columnName 属性和其他属性。
然而它并没有完全按预期工作。 如果我没有为User.userdata指定mappedBy属性,hibernate将自动创建一个表USERS_USERS_USERDATA,但据我所知并没有使用它。然而,它确实使用了我为 Userdata 类指定的表。

由于我对 Java 和 hibernate 也很陌生,所以我目前测试它所做的就是查看数据库模式 hibernate 在保留一些示例条目时创建。

结果,我完全不知道我这样做是否正确。我阅读了 hibernate 文档和相当多的 Google 结果,但它们似乎都没有处理我想要做的事情(带有“子类”和自己的主键的复合键)。

I have the following existing DB schema, which I'd like to recreate with Java and plain JPA annotations (using hibernate as provider, so hibernate specific annotations would work as a last resort):

CREATE TABLE users (
    user_id NUMBER NOT NULL                     -- pk
);

CREATE TABLE userdata_keys (
    userdata_key_id NUMBER NOT NULL,            -- pk
    key VARCHAR2(128) NOT NULL                  
);

CREATE TABLE users_userdata (
    user_id NUMBER NOT NULL,                    -- fk users.user_id
    userdata_key_id NUMBER NOT NULL,            -- fk userdata_keys.userdata_key_id 
    value VARCHAR2(256)                         
);

I've thus created the following classes and annotations:

class User {
    @Id
    Long id;
    @OneToMany
    Set<Userdata> userdata;
}

class UserdataKey {
    @Id
    Long id;
    String key;
}

class Userdata {
    String value;
    @EmbeddedId
    UserdataId userdataId;
}

@Embeddable
class UserdataId {
    User user;
    UserdataKey userdataKey;
}

I left out columnName attributes and other attributes of the entities here.
It does however not quite work as intended. If I do not specify a mappedBy attribute for User.userdata, hibernate will automatically create a table USERS_USERS_USERDATA, but as far as I've seen does not use it. It does however use the table which I specified for the Userdata class.

Since I'm rather new to Java and hibernate as well, all I do to test this currently is looking at the DB schema hibernate creates when persisting a few sample entries.

As a result, I'm entirely puzzled as to whether I'm doing this the right way at all. I read the hibernate documentation and quite a bunch of Google results, but none of them seemed to deal with what I want to do (composite key with "subclasses" with their own primary key).

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

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

发布评论

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

评论(1

裸钻 2024-12-13 15:01:27

mappedBy 属性在每个双向关联的一侧都是强制的。当关联是一对多时,mappedBy 属性放置在一侧(即在Useruserdata 上)您的案例中的字段)。

这是因为当关联是双向的时,关联的一侧始终是另一侧的反面,因此无需两次告诉 Hibernate 关联的映射方式(即使用哪个连接列或连接表)。

如果您准备好重新创建架构,我会做得正确(而且更容易),并在 users_userdata 中使用代理自动生成的键而不是复合键。在应用程序的所有层中,这将更容易处理。

The mappedBy attribute is mandatory at one of the sides of every bidirectional association. When the association is a one-to-many, the mappedBy attribute is placed ot the one- side (i.e. on the User's userdata field in your case).

That's because when an association is bidirectional, one side of the association is always the inverse of the other, so there's no need to tell twice to Hibernate how the association is mapped (i.e. which join column or join table to use).

If you're ready to recreate the schema, I would do it right (and easier), and use a surrogate auto-generated key in users_userdata rather than a composite one. This will be much easier to handle, in all the layers of your application.

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