2016-03-30 30 views
10

phiên bản ngắn cho vội vàng:cách tiếp cận tốt nhất để liên kết các loại thực thể đa dạng trong JPA

Có nhiều bảng/thực thể trong mô hình tên miền của tôi có cùng lĩnh vực (UUID). Có một bảng mà tôi cần liên kết các hàng/cá thể của các thực thể như vậy với các thực thể được quản lý bởi JPA khác. Nói cách khác, trường hợp của trường trong bảng liên kết đó sẽ không được biết trước. Hai cách tiếp cận tôi có thể nghĩ đến là:

  • Sử dụng một thực thể trừu tượng và một chiến lược TABLE_PER_CLASS, hoặc
  • sử dụng một @MappedSuperClass cửa hàng tên lớp của instance trong bảng liên kết là tốt, hoặc một cái gì đó tương tự cho phép tôi xác định logic để nhận được thể hiện thực tế từ bảng bên phải.

Cả hai đều có ưu điểm và nhược điểm về độ phức tạp và hiệu suất. Mà bạn tin là tốt nhất, có thể có một lựa chọn thứ ba, hoặc có bạn đã thử một cái gì đó như thế này trong quá khứ và sẽ tư vấn/mạnh mẽ cảnh báo chống lại?

Long phiên bản trong trường hợp bạn muốn nền hơn:

Tôi có một/mô hình đối tượng cơ sở dữ liệu trong đó nhiều loại có một lĩnh vực chung: nhận dạng duy nhất (UUID). Lý do cho điều này là trường hợp của các loại này có thể bị thay đổi. Các thay đổi theo mô hình lệnh và dữ liệu của chúng có thể được đóng gói và chính nó vẫn tồn tại. Hãy gọi sự thay đổi này là "đột biến". Nó phải có khả năng tìm ra những đột biến tồn tại trong cơ sở dữ liệu cho bất kỳ thực thể nào, và ngược lại, trên thực thể mà một đột biến được lưu trữ hoạt động.

Lấy đối tượng sau đây với UUIDs như một (rất đơn giản) ví dụ: mutable entities

Để lưu trữ "đột biến", chúng tôi sử dụng một bảng/thực thể gọi là MutationHolder. Để liên kết một đột biến với thực thể đích của nó, có MutationEntityLink. Lý do duy nhất dữ liệu này không phải là trực tiếp trên MutationHolder là bởi vì có thể có liên kết trực tiếp hay gián tiếp, nhưng đó là ít xung yếu ở đây vì vậy tôi rời nó ra: mutation entities

Câu hỏi đặt ra đi xuống đến làm thế nào tôi có thể mô hình entity trường trong MutationEntityLink. Có hai cách tiếp cận mà tôi có thể nghĩ đến.

Cách thứ nhất là tạo một lớp có chú thích @Entity có chú giải với trường UUID. Customer, ContractAddress sẽ mở rộng. Vì vậy, nó là một chiến lược TABLE_PER_CLASS. Tôi cho rằng tôi có thể sử dụng loại này cho trường entity, mặc dù tôi không chắc chắn. Tuy nhiên, tôi lo sợ điều này có thể có một hình phạt nghiêm trọng về hiệu suất vì JPA sẽ cần phải truy vấn nhiều bảng để tìm ra cá thể thực tế.

Cách thứ hai chỉ đơn giản là sử dụng @MappedSuperClass và chỉ lưu trữ UUID cho một thực thể trong trường entity của MutationEntityLink. Để có được thực thể thực sự với UUID đó, tôi phải giải quyết nó theo chương trình. Thêm một cột bổ sung với tên lớp của thực thể, hoặc một cái gì đó khác cho phép tôi xác định nó hoặc dán nó vào một truy vấn JPQL sẽ làm. Điều này đòi hỏi nhiều công việc hơn nhưng có vẻ hiệu quả hơn. Tôi không thích viết mã một số lớp tiện ích hoặc thực hiện một số chú thích tùy chỉnh/phản chiếu nếu cần.

Câu hỏi của tôi là phương pháp nào trong số những phương pháp này có vẻ tốt nhất? Ngoài ra, bạn có thể có một đề nghị tốt hơn, hoặc thông báo tôi đang thiếu một cái gì đó; ví dụ, có thể có một cách để thêm một cột kiểu ngay cả với TABLE_PER_CLASS thừa kế để trỏ JPA vào bảng bên phải? Có lẽ bạn đã thử một cái gì đó như thế này và muốn cảnh báo tôi về nhiều vấn đề phát sinh.

Một số thông tin bổ sung:

  • Chúng tôi tạo ra cấu trúc CSDL, vì vậy chúng tôi có thể thêm bất cứ điều gì chúng ta muốn.
  • Một chiến lược kế thừa bảng duy nhất không phải là một tùy chọn. Các bảng phải duy trì riêng biệt. Đối với cùng một lý do, tham gia thừa kế dường như không phù hợp hoặc.
  • Nhà cung cấp JPA là Hibernate và sử dụng những thứ không thuộc tiêu chuẩn JPA không phải là vấn đề.

Trả lời

6

Nếu các đối tượng không có bất kỳ điểm chung nào ngoài việc có uuid, tôi sẽ sử dụng cách tiếp cận thứ hai mà bạn mô tả: sử dụng MappedSuperclass. Việc tạo một superclass chung một thực thể sẽ ngăn cản bạn sử dụng một chiến lược thừa kế khác nếu cần, sẽ yêu cầu một bảng cho thực thể siêu đó ngay cả khi không có cá thể nào tồn tại và từ một quan điểm kinh doanh nó chỉ là sai.

Bản thân liên kết có thể được triển khai theo nhiều cách, ví dụ: bạn có thể phân lớp MutationEntityLink cho mỗi thực thể để ánh xạ (ví dụ: CustomerMutationEntityLink v.v.) hoặc làm như bạn đã mô tả nó, tức là chỉ lưu trữ uuid cũng như một số thông tin phân biệt/loại và giải quyết theo chương trình (chúng tôi đang sử dụng phương pháp đó cho btw tương tự.).

+0

Rất vui khi biết bạn đang thực sự sử dụng phương pháp đó. Nó cho thấy rằng nó khả thi. Tôi nghĩ rằng subclassing MutationEntityLink cho mỗi thực thể được ánh xạ sẽ rất bất tiện, do đó, một loại cột phân biệt âm thanh tốt nhất ngay bây giờ. –

+0

@G_H có đó là lý do để quyết định chống lại các lớp con. – Thomas

+1

Tôi thích ý tưởng của @Thomas về phân lớp MutationEntityLink cho mọi thực thể. Vì đó là một lớp kỹ thuật cung cấp liên kết giữa các đột biến và các thực thể của bạn, tôi sẽ đi cho kế thừa bảng đơn. Bảng sẽ có cột phân biệt đối xử của nó và một cột khóa ngoài cho mỗi thực thể. Bảng có thể không phải là biểu diễn thanh lịch nhất của mô hình miền của bạn, nhưng bạn có thể nhận được hiệu suất tốt từ đó. –

2

Bạn cần sử dụng @MappedSuperclass trong khi kế thừa các liên kết/phương pháp/thuộc tính trong khi TABLE_PER_CLASS thường được sử dụng khi bạn có tổ chức và thực thể con. Nếu có các thực thể có liên kết với lớp cơ sở trong mô hình, thì hãy sử dụng TABLE_PER_CLASS vì lớp cơ sở hoạt động như một thực thể. Nếu không, kể từ khi lớp cơ sở sẽ bao gồm các thuộc tính/thuộc tính và phương pháp mà là chung cho các đơn vị này không liên quan đến nhau, sử dụng @MappedSuperclass sẽ là một ý tưởng tốt hơn

example1: Bạn cần phải thiết lập báo động đối với một số hoạt động khác nhau như "uống thuốc", "gọi mẹ", "đi đến bác sĩ" vv Nội dung của tin nhắn báo động không quan trọng, bạn sẽ cần một lời nhắc nhở. Vì vậy, hãy sử dụng TABLE_PER_CLASS từ thông báo cảnh báo, đây là lớp cơ sở của bạn giống như một thực thể ở đây.

Ví dụ2: Giả sử lớp cơ sở AbstractDomainObject cho phép bạn tạo ID đăng nhập, tên đăng nhập, ngày tạo/sửa đổi cho từng đối tượng không có tổ chức nào có liên kết với lớp cơ sở, bạn sẽ cần chỉ định liên kết vì mục đích thanh toán bù trừ sau này, như "Công ty", "Đại học" vv Trong tình huống này, việc sử dụng @MappedSuperclass sẽ tốt hơn.

+0

Sự khác biệt giữa một siêu lớp được ánh xạ và chiến lược kế thừa bảng cho mỗi lớp đã rõ ràng đối với tôi. Thách thức trong tình huống của tôi là trên thực tế có một bảng cần tham chiếu các thực thể đang triển khai lớp trừu tượng, nhưng đối với mô hình miền và hiệu năng '@ MappedSuperClass' có ý nghĩa hơn TABLE_PER_CLASS, vì vậy hãy sử dụng cần tạo logic tra cứu cho đúng loại thực thể. Câu hỏi đặt ra cho dù đó là khả thi (Thomas xác nhận như vậy) và nếu có một giải pháp hiện có/thực hành tốt nhất. –

Các vấn đề liên quan