Выбор составного первичного ключа - то, что работает с Hibernate, не работает с EclipseLink. Зачем? - PullRequest
1 голос
/ 02 апреля 2011

У меня есть две таблицы.

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 профиль и * ProfileItem.

1 Profile --- * ProfileItems (один профиль может иметь несколько ProfileItems).

Примечание: 1. Это отношение один-ко-многим от профиля к profileItem. 2. Это однонаправленные отношения.

PK для профиля - это profile_id.

PK для ProfileItem - составной первичный ключ (profile_id, from_id)

Во-первых, я хотел бы пожаловаться на то, что EclipseLink не работает как Hibernate:

1-я проблема с 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, если она не решает проблемы переносимости.

Существует вторая проблема с сохранением родительских и каскадных дочерних элементов, которая работает в режиме гибернации и не работает с eclipselink. Я опубликую это как отдельный вопрос, чтобы сохранить его кратким и точным.

Спасибо. Арун Кандрегула

Ответы [ 2 ]

2 голосов
/ 04 апреля 2011

Это похоже на ошибку в обработке аннотаций. Пожалуйста, зарегистрируйте эту ошибку на EclipseLink, если она все еще встречается в последней версии.

Обратите внимание, что @JoinColumn обычно используется для @ManyToOne или @OneToOne, а не @OneToMany. Обычно для @OneToMany у вас должен быть обратный @ManyToOne и использовать mappedBy. Использование @JoinColumn для @OneToMany - это специальный тип @OneToMany, который поддерживает внешний ключ целевой таблицы. Поскольку profile_id является частью вашего первичного ключа, чтобы быть правильным, вам действительно нужно вернуть @ManyToOne, затем вы можете удалить profileId и просто добавить @Id в @ ManyToOne.

0 голосов
/ 14 апреля 2011

Я унаследовал код, подобный этому (и отлично работает с Hibernate):

@ OneToMany @JoinColumn (name = "prod_no", referencedColumnName = "prod_no") Частная коллекция предметов;

joinColumn используется для oneToMany;)

...