JPA: sự khác biệt giữa @JoinColumn và @PrimaryKeyJoinColumn?


82

Sự khác biệt chính xác giữa @JoinColumnvà là @PrimaryKeyJoinColumngì?

Bạn sử dụng @JoinColumncho các cột là một phần của khóa ngoại. Một cột điển hình có thể trông giống như (ví dụ: trong một bảng nối với các thuộc tính bổ sung):

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

Điều gì xảy ra nếu tôi quảng cáo cột cũng là một PK (hay còn gọi là mối quan hệ xác định)? Vì cột bây giờ là PK, tôi phải gắn thẻ nó bằng @Id:

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

Bây giờ câu hỏi là:

@Id+ Có @JoinColumngiống nhau @PrimaryKeyJoinColumnkhông ?:

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

Nếu không, @PrimaryKeyJoinColumnở đó để làm gì?

Câu trả lời:


53

Điều gì xảy ra nếu tôi quảng cáo cột cũng là một PK (hay còn gọi là mối quan hệ xác định)? Vì cột bây giờ là PK, tôi phải gắn thẻ nó bằng @Id (...).

Sự hỗ trợ nâng cao này của các số nhận dạng có nguồn gốc thực sự là một phần của nội dung mới trong JPA 2.0 (xem phần 2.4.1 Các phím chính tương ứng với các nhận dạng có nguồn gốc trong đặc tả JPA 2.0), JPA 1.0 không cho phép Idtrên một OneToOnehoặc ManyToOne. Với JPA 1.0, bạn phải sử dụng PrimaryKeyJoinColumnvà cũng xác định Basic Idánh xạ cho cột khóa ngoại.

Bây giờ câu hỏi là: @Id + @JoinColumn có giống với @PrimaryKeyJoinColumn không?

Bạn có thể có được một kết quả tương tự nhưng sử dụng một Idtrên OneToOnehoặc ManyToOneđơn giản hơn nhiều và là cách ưa thích để lập bản đồ định danh có nguồn gốc với JPA 2.0. PrimaryKeyJoinColumnvẫn có thể được sử dụng trong chiến lược kế thừa JOINED . Dưới phần có liên quan từ thông số kỹ thuật JPA 2.0:

11.1.40 Chú thích PrimaryKeyJoinColumn

Các PrimaryKeyJoinColumnchú thích rõ một cột khóa chính được sử dụng như một chìa khóa nước ngoài để tham gia vào một bảng khác.

Các PrimaryKeyJoinColumnchú thích được sử dụng để tham gia bảng tiểu học của một lớp con thực thể trong JOINED chiến lược map vào bảng chính của lớp cha của nó; nó được sử dụng trong một SecondaryTablechú thích để nối một bảng phụ với một bảng chính; và nó có thể được sử dụng trong OneToOne ánh xạ trong đó khóa chính của thực thể tham chiếu được sử dụng làm khóa ngoại cho thực thể được tham chiếu [108] .

...

Nếu không có PrimaryKeyJoinColumn chú thích nào được chỉ định cho một lớp con trong chiến lược ánh xạ JOINED, các cột khóa ngoại được giả định có cùng tên với các cột khóa chính của bảng chính của lớp cha.

...

Ví dụ: Lớp con Khách hàng và Khách hàng Có giá trị

@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] Các cơ chế id dẫn xuất được mô tả trong phần 2.4.1.1 hiện được ưu tiên hơn PrimaryKeyJoinColumncho trường hợp ánh xạ OneToOne.

Xem thêm


Nguồn này http://weblogs.java.net/blog/felipegaucho/archive/2009/10/24/jpa-join-table-additional-state nói rằng việc sử dụng @ManyToOne và @Id hoạt động với JPA 1.x. Ai đúng bây giờ?

Tác giả đang sử dụng phiên bản EclipseLink tương thích JPA 2.0 phát hành trước (phiên bản 2.0.0-M7 tại thời điểm bài viết) để viết một bài báo về JPA 1.0 (!). Bài viết này gây hiểu lầm, tác giả đang sử dụng thứ KHÔNG thuộc JPA 1.0.

Đối với bản ghi, hỗ trợ Idbật OneToOneManyToOneđã được thêm vào EclipseLink 1.1 (xem thông báo này từ James Sutherland , người đồng hành EclipseLink và người đóng góp chính của sách wiki Java Persistence ). Nhưng tôi xin khẳng định, đây KHÔNG phải là một phần của JPA 1.0.


Nguồn này weblogs.java.net/blog/felipegaucho/archive/2009/10/24/… nói rằng việc sử dụng @ManyToOne và @Id hoạt động với JPA 1.x. Ai đúng bây giờ?
Kawu

ĐỒNG Ý. Cám ơn giải thích rõ ràng. Tôi đúng rằng ví dụ xấu mà một tham chiếu đến sử dụng @IdClass sai? Không nên đặt chú thích @Id tại các cột riêng biệt (thừa / trùng lặp) trong lớp thực thể có đúng không? (VEN mặc dù tôi biết rằng việc sử dụng @IdClass không được khuyến khích nữa)
Kawu

Ý tôi là, nên có hai thuộc tính trong lớp: @Id @Column private String sports; và @Id @Column private String cạnh tranh; chỉ để chỉ định PK phải không?
Kawu

@Kawu Tôi xin lỗi nhưng thành thật mà nói, quá khó để thảo luận điều này trong một hộp bình luận nhỏ. Tôi thậm chí không chắc mình hiểu bạn đang nói gì. Nếu bạn có một câu hỏi cụ thể khác, tôi khuyên bạn nên chọn một triển khai JPA và thử nghiệm một chút hoặc đăng một câu hỏi mới với một ví dụ đầy đủ (và phiên bản JPA). Điều này sẽ làm cho mọi thứ dễ dàng hơn nhiều.
Pascal Thivent

37

Tôi thường phân biệt hai thứ này qua sơ đồ này:

Sử dụng PrimaryKeyJoinColumn

nhập mô tả hình ảnh ở đây

Sử dụng JoinColumn

nhập mô tả hình ảnh ở đây


2
@yusher, PrimaryKeyJoinColumnsử dụng cùng một giá trị khóa chính để nối hai bảng và JoinColumnkhóa chính của bảng chính sẽ trở thành khóa ngoại trong bảng khác.
Sam YC

2

Tôi biết đây là một bài viết cũ, nhưng thời điểm tốt để sử dụng PrimaryKeyColumnsẽ là nếu bạn muốn có một mối quan hệ một chiều hoặc có nhiều bảng chia sẻ cùng một id.

Nói chung, đây là một ý tưởng tồi và sẽ tốt hơn nếu sử dụng các mối quan hệ khóa ngoại với JoinColumn.

Phải nói rằng, nếu bạn đang làm việc trên một cơ sở dữ liệu cũ đã sử dụng một hệ thống như thế này thì đó sẽ là thời điểm tốt để sử dụng nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.