JPA: różnica między @JoinColumn i @PrimaryKeyJoinColumn?

83

Jaka jest dokładna różnica między @JoinColumni @PrimaryKeyJoinColumn?

Używasz @JoinColumndla kolumn, które są częścią klucza obcego. Typowa kolumna mogłaby wyglądać (np. W tabeli łączenia z dodatkowymi atrybutami):

@ManyToOne
@JoinColumn(name = "...")
private OtherClass oc;

Co się stanie, jeśli wypromuję kolumnę, aby była również / PK (inaczej identyfikującą relację)? Ponieważ kolumna jest teraz PK, muszę oznaczyć ją @Id:

@Id
@ManyToOne
@JoinColumn(name = "...")
private OtherClass oc;

Teraz pytanie brzmi:

Czy @Id+ to @JoinColumnto samo co just @PrimaryKeyJoinColumn?:

@ManyToOne
@PrimaryKeyJoinColumn(name = "...")
private OtherClass oc;

Jeśli nie, po co @PrimaryKeyJoinColumntam jest?

Kawu
źródło

Odpowiedzi:

55

Co się stanie, jeśli wypromuję kolumnę, aby była również / PK (inaczej identyfikującą relację)? Ponieważ kolumna jest teraz PK, muszę oznaczyć ją @Id (...).

Ta ulepszona obsługa identyfikatorów pochodnych jest w rzeczywistości częścią nowej rzeczy w JPA 2.0 (patrz sekcja 2.4.1 Klucze podstawowe odpowiadające tożsamościom pochodnym w specyfikacji JPA 2.0), JPA 1.0 nie zezwala Idna OneToOnelub ManyToOne. W przypadku JPA 1.0 musiałbyś użyć PrimaryKeyJoinColumni zdefiniować Basic Idmapowanie dla kolumny klucza obcego.

Teraz pytanie brzmi: czy @Id + @JoinColumn to to samo, co tylko @PrimaryKeyJoinColumn?

Możesz uzyskać podobny wynik, ale użycie Idon OneToOnelub ManyToOnejest znacznie prostsze i jest preferowanym sposobem mapowania identyfikatorów pochodnych za pomocą JPA 2.0. PrimaryKeyJoinColumnmoże być nadal używany w strategii dziedziczenia POŁĄCZONYCH . Poniżej odpowiednia sekcja ze specyfikacji JPA 2.0:

11.1.40 Adnotacja PrimaryKeyJoinColumn

PrimaryKeyJoinColumnAdnotacji określa kolumnę klucza podstawowego, który jest używany jako klucz obcy do przyłączenia się do innego stolika.

PrimaryKeyJoinColumnAdnotacja jest wykorzystywany do przyłączenia się do pierwotnej tabeli podklasy podmiotem w JOINED strategii przyporządkowania dla głównej tablicy jego nadrzędnej; jest używany w SecondaryTableadnotacji do łączenia tabeli dodatkowej z tabelą podstawową; i może być używany w OneToOne odwzorowaniu, w którym klucz podstawowy obiektu odniesienia jest używany jako klucz obcy do obiektu odniesienia [108] .

...

Jeśli PrimaryKeyJoinColumn adnotacja nie jest określona dla podklasy w strategii mapowania JOINED, zakłada się, że kolumny klucza obcego mają takie same nazwy, jak kolumny klucza podstawowego tabeli podstawowej nadklasy.

...

Przykład: podklasy Customer i ValuedCustomer

@Entity
@Table(name="CUST")
@Inheritance(strategy=JOINED)
@DiscriminatorValue("CUST")
public class Customer { ... }

@Entity
@Table(name="VCUST")
@DiscriminatorValue("VCUST")
@PrimaryKeyJoinColumn(name="CUST_ID")
public class ValuedCustomer extends Customer { ... }

[108] Wyprowadzone mechanizmy identyfikacyjne opisane w sekcji 2.4.1.1 mają być teraz preferowane w PrimaryKeyJoinColumnprzypadku mapowania OneToOne.

Zobacz też


To źródło http://weblogs.java.net/blog/felipegaucho/archive/2009/10/24/jpa-join-table-additional-state stwierdza, że ​​używanie @ManyToOne i @Id działa z JPA 1.x. Kto ma teraz rację?

Autor korzysta z przedpremierowej wersji EclipseLink zgodnej z JPA 2.0 (wersja 2.0.0-M7 w czasie pisania artykułu) do napisania artykułu o JPA 1.0 (!). Ten artykuł jest mylący, autor używa czegoś, co NIE jest częścią JPA 1.0.

Dla przypomnienia , wsparcie dla Idon OneToOnei ManyToOnezostało dodane w EclipseLink 1.1 (zobacz tę wiadomość od Jamesa Sutherlanda , comittera EclipseLink i głównego współautora książki wiki Java Persistence ). Ale pozwól mi nalegać, to NIE jest część JPA 1.0.

Pascal Thivent
źródło
To źródło weblogs.java.net/blog/felipegaucho/archive/2009/10/24/… stwierdza, że ​​używanie @ManyToOne i @Id działa z JPA 1.x. Kto ma teraz rację?
Kawu
DOBRZE. Dzięki za wyjaśnienie tego. Mam rację, że zły przykład, o którym mowa, niewłaściwie używa @IdClass? Czy adnotacje @Id nie powinny być umieszczone w oddzielnych (nadmiarowych / zduplikowanych) kolumnach w klasie jednostki, aby były poprawne? (choć wiem, że używanie @IdClass nie jest już zalecane)
Kawu
Chodzi mi o to, że w klasie powinny znajdować się dwie właściwości: @Id @Column private String instytucja; i @Id @Column prywatny konkurs String; tylko określić PK, prawda?
Kawu
@Kawu Przepraszam, ale szczerze mówiąc, zbyt trudno jest o tym dyskutować w małym polu komentarza. Nie jestem nawet pewien, czy zrozumiałem, o czym mówisz. Jeśli masz inne konkretne pytanie, proponuję albo wybrać implementację JPA i trochę poeksperymentować, albo opublikować nowe pytanie z pełnym przykładem (i wersją JPA). To znacznie ułatwiłoby sprawę.
Pascal Thivent
38

Zwykle rozróżniam te dwa za pomocą tego schematu:

Posługiwać się PrimaryKeyJoinColumn

wprowadź opis obrazu tutaj

Posługiwać się JoinColumn

wprowadź opis obrazu tutaj

Sam YC
źródło
3
@yusher, PrimaryKeyJoinColumnużyj tej samej wartości klucza podstawowego, aby połączyć dwie tabele, a JoinColumnklucz podstawowy tabeli głównej stanie się kluczem obcym w innej tabeli.
Sam YC
2

Wiem, że to stary post, ale dobry moment do wykorzystania PrimaryKeyColumnbyłby, gdybyś chciał relacji jednokierunkowej lub miał wiele tabel o tym samym identyfikatorze.

Ogólnie jest to zły pomysł i lepiej byłoby użyć relacji z kluczem obcym z JoinColumn.

Powiedziawszy to, jeśli pracujesz na starszej bazie danych, która korzystała z takiego systemu, to byłby dobry moment na jej użycie.

Philip Read
źródło