复合主键选择 - 适用于 Hibernate 的方法不适用于 EclipseLink。为什么?

发布于 2024-10-28 19:46:10 字数 2712 浏览 5 评论 0原文

我有两张桌子。

CREATE TABLE profile_table
( 
    profile_id NUMBER(10,0) PRIMARY KEY, 
    creator_manager_id NUMBER(10,0), 
    lastupdate DATE, 
    description VARCHAR2(255 BYTE), 
    profile_name VARCHAR2(255 BYTE), 
    creatorname VARCHAR2(255 BYTE)
);

CREATE TABLE profile_basket_table
( 
    profile_id NUMBER(10,0), 
    from_id  NUMBER(10,0), 
    action NUMBER(10,0),
    constraint pbt_pk_constraint PRIMARY KEY(profile_id, from_id),
    constraint pbt_fk_constraint FOREIGN KEY(profile_id) REFERENCES profile_table(profile_id)
);

我有 1 个个人资料和 * 个个人资料项目。

1 个配置文件 --- * 配置文件项(一个配置文件可以有多个配置文件项)。

注意: 1. profile 到 profileItem 是一对多的关系。 2.它是一种单向关系。

配置文件的 PK 是 profile_id。

ProfileItem 的 PK 是一个复合主键( profile_id, from_id )

首先,我想抱怨 EclipseLink 不像 Hibernate 那样工作:

EclipseLink 的第一个问题: 只是因为我在子实体中有一个名为 ProfileItem 的复合主键,它迫使我使用 JoinColumns。我无法使用 @JoinColumns,因为其他列 from_id 不是任何其他表的外键。 我最初使用与 hibernate 完美配合的相同注释,如下所示:

@Entity
@Table(name="profile_table")
class Profile {

    @Id
    @Column(name="profile_id")
    private Integer profileId ;
     ...

    /**
     *  WORKS WITH HIBERNATE AS PERSISTENCE PROVIDER, BUT FAILS WITH ECLIPSELINK
    */
    @OneToMany( cascade = CascadeType.ALL )
    @JoinColumn( name= "profile_id", referencedColumnName="profile_id" )
    private Set<XVMUpdateProfileItem> profileItems = null;

    ...
}

上面的代码在 eclipselink 中抛出以下错误:

The @JoinColumns on the annotated element [field profileItems] from the entity class [class arun.ucerelay.datastructures.XVMUpdateProfile] is incomplete. When the source entity class uses a composite primary key, a @JoinColumn must be specified for each join column using the @JoinColumns. Both the name and the referencedColumnName elements must be specified in each such @JoinColumn.

如何通过 @JoinColumn 注释的几种排列和组合,我设法使其能够用于加载配置文件和相关配置文件项。

/**
 *  WORKS WITH ECLIPSELINK AS PERSISTENCE PROVIDER
 */

@OneToMany( cascade = CascadeType.ALL)
@JoinColumns({
    @JoinColumn( name= "profile_id", referencedColumnName="profile_id" , insertable = true, updatable = true),
    @JoinColumn( name= "profile_id", referencedColumnName="profile_id" , nullable = false)    
})
private Set<XVMUpdateProfileItem> profileItems = null;

再次声明 @JoinColumn 是没有意义的......但奇怪的是它与 eclipselink 一起工作。这是一个错误。不是吗?

谁能告诉我我是否遗漏了什么?还有其他正确的方法来实现单向关系,请告诉我。

这是关于 @JoinColumns 的错误,不是吗?我应该记录它吗?

这是否称为从一个持久性提供者到另一个持久性提供者的“可移植性”? 如果不解决可移植性,使用JPA规范有什么用。

保存父项和级联子项还有第二个问题,它适用于 hibernate,但不适用于 eclipselink。我将其作为一个单独的问题发布,以保持简短和准确。

谢谢。 阿伦·坎德雷古拉

I have two tables.

CREATE TABLE profile_table
( 
    profile_id NUMBER(10,0) PRIMARY KEY, 
    creator_manager_id NUMBER(10,0), 
    lastupdate DATE, 
    description VARCHAR2(255 BYTE), 
    profile_name VARCHAR2(255 BYTE), 
    creatorname VARCHAR2(255 BYTE)
);

CREATE TABLE profile_basket_table
( 
    profile_id NUMBER(10,0), 
    from_id  NUMBER(10,0), 
    action NUMBER(10,0),
    constraint pbt_pk_constraint PRIMARY KEY(profile_id, from_id),
    constraint pbt_fk_constraint FOREIGN KEY(profile_id) REFERENCES profile_table(profile_id)
);

I have 1 Profile and * ProfileItem.

1 Profile --- * ProfileItems ( One profile can have Many ProfileItems).

Note : 1. Its a one-to-many relationship from profile to profileItem.
2. Its a unidirectional relationship.

PK for Profile is profile_id.

PK for ProfileItem is a composite primary key ( profile_id, from_id )

Firstly, I would I like to complain that EclipseLink doesnt work like Hibernate :

1st Problem with EclipseLink:
Just becasue I have a composite primary key in child entity called ProfileItem, its forcing me to use JoinColumns. I cant use @JoinColumns as other column from_id is not a foreign key to any other table.
I initially used same annotation which worked perfectly with hibernate as follows :

@Entity
@Table(name="profile_table")
class Profile {

    @Id
    @Column(name="profile_id")
    private Integer profileId ;
     ...

    /**
     *  WORKS WITH HIBERNATE AS PERSISTENCE PROVIDER, BUT FAILS WITH ECLIPSELINK
    */
    @OneToMany( cascade = CascadeType.ALL )
    @JoinColumn( name= "profile_id", referencedColumnName="profile_id" )
    private Set<XVMUpdateProfileItem> profileItems = null;

    ...
}

Above code throws following error with eclipselink :

The @JoinColumns on the annotated element [field profileItems] from the entity class [class arun.ucerelay.datastructures.XVMUpdateProfile] is incomplete. When the source entity class uses a composite primary key, a @JoinColumn must be specified for each join column using the @JoinColumns. Both the name and the referencedColumnName elements must be specified in each such @JoinColumn.

Some how with several permutations and combinations of @JoinColumn annotation, I managed to get this working for loading profiles and related profile items.

/**
 *  WORKS WITH ECLIPSELINK AS PERSISTENCE PROVIDER
 */

@OneToMany( cascade = CascadeType.ALL)
@JoinColumns({
    @JoinColumn( name= "profile_id", referencedColumnName="profile_id" , insertable = true, updatable = true),
    @JoinColumn( name= "profile_id", referencedColumnName="profile_id" , nullable = false)    
})
private Set<XVMUpdateProfileItem> profileItems = null;

This doesnt make sense to declare @JoinColumn again...But weirdly it works with eclipselink. This is a bug. Isnt it?

Can anyone tell me if I am missing anything ? Is there any other right way of implementing unidirectional relationship, please tell me.

This is a bug about @JoinColumns isnt it ? Should I log it ?

Is this called "portability" from one persistence provider to another ???????
What is the use of using JPA specification if it doesnt solve portability.

There is a second problem with saving of parent and cascading child items which works with hibernate and doesnt work with eclipselink. Ill post it as a separate question to keep this short and precise.

Thanks.
Arun Kandregula

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

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

发布评论

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

评论(2

逆流 2024-11-04 19:46:10

这似乎是注释处理中的一个错误。如果最新版本上仍然出现此错误,请在 EclipseLink 上记录此错误。

请注意,@JoinColumn 通常用于@ManyToOne 或@OneToOne,而不是@OneToMany。通常,对于@OneToMany,您应该有一个逆@ManyToOne并使用mappedBy。在 @OneToMany 上使用 @JoinColumn 是一种特殊类型的 @OneToMany,它本身维护目标表的外键。由于 profile_id 是主键的一部分,为了正确起见,您确实应该返回 @ManyToOne,然后您可以删除 profileId 并将 @Id 添加到 @ManyToOne。

This seems to be a bug in the annotation processing. Please log this bug on EclipseLink if it still occurs on the latest version.

Note that @JoinColumn is normally used for @ManyToOne or @OneToOne, not @OneToMany. Normally for a @OneToMany you should have an inverse @ManyToOne and use the mappedBy. Using a @JoinColumn on a @OneToMany is a special type of @OneToMany that maintains the target table's foreign key itself. Since the profile_id is part of your primary key, to be correct you really should have the @ManyToOne back, you could then remove the profileId and just add @Id to the @ManyToOne.

溺渁∝ 2024-11-04 19:46:10

我继承了这样的代码(并且与 hibernate 一起工作正常):

@OneToMany
@JoinColumn(name="prod_no",referencedColumnName="prod_no")
私人收藏物品;

joinColumn 用于 oneToMany ;)

i have inherited a code like this (and working fine with hibernate):

@OneToMany
@JoinColumn(name="prod_no", referencedColumnName="prod_no")
private Collection items;

joinColumn is used for oneToMany ;)

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