Bên sở hữu của người khác trong một bản đồ ORM là gì?


128

Chính xác thì bên sở hữu có nghĩa là gì? Một lời giải thích với một số ví dụ ánh xạ ( một đến nhiều, một với nhiều, nhiều đến một ) là gì?

Văn bản sau đây là đoạn trích từ mô tả của @OneToOne trong tài liệu Java EE 6. Bạn có thể thấy khái niệm sở hữu bên trong nó.

Xác định một liên kết có giá trị đơn lẻ với một thực thể khác có bội số một-một. Thông thường không cần thiết phải xác định rõ ràng thực thể đích liên quan vì nó thường có thể được suy ra từ loại đối tượng được tham chiếu. Nếu mối quan hệ là hai chiều, bên không sở hữu phải sử dụng phần tử mappedBy của chú thích OneToOne để chỉ định trường quan hệ hoặc thuộc tính của bên sở hữu.



5
Tôi đã bị mất cho đến khi tôi đọc được điều này: javacodegeek.com/2013/04/ Khăn
darga33 7/11/2016

2
Bảng DB với cột khóa ngoại được coi là bên sở hữu. Vì vậy, thực thể kinh doanh đại diện cho bảng DB đó là Chủ sở hữu (phía sở hữu) của mối quan hệ đó. Không cần thiết, nhưng hầu hết các trường hợp Bên sở hữu sẽ có chú thích @JoinColumn.
Diablo

Câu trả lời:


202

Tại sao khái niệm về một bên sở hữu là cần thiết:

Ý tưởng về một khía cạnh sở hữu của mối quan hệ hai chiều xuất phát từ thực tế là trong các cơ sở dữ liệu quan hệ không có quan hệ hai chiều như trong trường hợp của các đối tượng. Trong cơ sở dữ liệu chúng ta chỉ có quan hệ một chiều - khóa ngoại.

Lý do cho cái tên 'bên sở hữu' là gì?

Phía sở hữu của mối quan hệ được theo dõi bởi Hibernate là phía của mối quan hệ sở hữu khóa ngoại trong cơ sở dữ liệu.

Vấn đề mà khái niệm sở hữu bên giải quyết là gì?

Lấy một ví dụ về hai thực thể được ánh xạ mà không cần khai báo một bên sở hữu:

@Entity
@Table(name="PERSONS")
public class Person {
    @OneToMany
    private List<IdDocument>  idDocuments;
}

@Entity
@Table(name="ID_DOCUMENTS")
public class IdDocument {
    @ManyToOne
    private Person person;
}

Từ quan điểm OO, ánh xạ này xác định không phải là một mối quan hệ hai chiều, mà là hai mối quan hệ đơn hướng riêng biệt.

Ánh xạ sẽ tạo ra không chỉ các bảng PERSONSID_DOCUMENTS, mà còn tạo ra một bảng kết hợp thứ ba PERSONS_ID_DOCUMENTS:

CREATE TABLE PERSONS_ID_DOCUMENTS
(
  persons_id bigint NOT NULL,
  id_documents_id bigint NOT NULL,
  CONSTRAINT fk_persons FOREIGN KEY (persons_id) REFERENCES persons (id),
  CONSTRAINT fk_docs FOREIGN KEY (id_documents_id) REFERENCES id_documents (id),
  CONSTRAINT pk UNIQUE (id_documents_id)
)

Chú ý khóa chính pktrên ID_DOCUMENTSchỉ. Trong trường hợp này, Hibernate theo dõi cả hai mặt của mối quan hệ một cách độc lập: Nếu bạn thêm một tài liệu vào quan hệ Person.idDocuments, nó sẽ chèn một bản ghi vào bảng kết hợp PERSON_ID_DOCUMENTS.

Mặt khác, nếu chúng ta gọi idDocument.setPerson(person), chúng ta sẽ thay đổi người nước ngoài person_id trên bàn ID_DOCUMENTS. Hibernate đang tạo hai quan hệ một chiều (khóa ngoại) trên cơ sở dữ liệu, để thực hiện một quan hệ đối tượng hai chiều.

Làm thế nào khái niệm sở hữu bên giải quyết vấn đề:

Nhiều lần những gì chúng tôi muốn chỉ là một khoá ngoại trên bảng ID_DOCUMENTShướng PERSONSvà bảng gắn thêm.

Để giải quyết vấn đề này, chúng ta cần cấu hình Hibernate để ngừng theo dõi các sửa đổi về mối quan hệ Person.idDocuments. Hibernate chỉ nên theo dõi khác bên của mối quan hệ IdDocument.person, và làm như vậy chúng ta thêm mappedBy :

@OneToMany(mappedBy="person")
private List<IdDocument>  idDocuments;

Nó có nghĩa là mappedBy?

Điều này có nghĩa đại loại như: "các sửa đổi ở phía bên này của mối quan hệ đã được ánh xạ Ở phía bên kia của mối quan hệ IdDocument.person, vì vậy không cần phải theo dõi riêng ở đây trong một bảng phụ."

Có bất kỳ GOTCHA, hậu quả?

Sử dụng mappedBy , Nếu chúng tôi chỉ gọi person.getDocuments().add(document), khóa ngoại ID_DOCUMENTSsẽ KHÔNG được liên kết với tài liệu mới, vì đây không phải là phía sở hữu / theo dõi của mối quan hệ!

Để liên kết tài liệu với người mới, bạn cần gọi một cách rõ ràng document.setPerson(person), vì đó là khía cạnh sở hữu của mối quan hệ.

Khi sử dụng mappedBy , nhà phát triển có trách nhiệm phải biết phía sở hữu là gì và cập nhật phía chính xác của mối quan hệ để kích hoạt tính bền vững của mối quan hệ mới trong cơ sở dữ liệu.


17
Câu trả lời tốt nhất tôi tìm thấy giải thích Học thuyết 'mappedBy' + 'inversedBy'.
Kurt Zhong

1
Cảm ơn đã chỉ định ánh xạ & lý do đằng sau khái niệm này.
Mohamel

1
Tôi không biết liệu mọi thứ đã thay đổi hay chưa, nhưng trên Hibernate 5.0.9. Nếu tôi "chỉ gọi person.getDocuments().add(document)", thì ngủ đông sẽ cập nhật khóa ngoại ID_DOCUMENTS.
K.Nicholas

1
@Karl Nicholas, xin chào, đồng ý với bạn, chúng tôi có thuộc tính xếp tầng trên @OneToManychú thích có thể được đặt thành PERSIST trong trường hợp này ngủ đông sẽ lưu tất cả các thực thể được liên kết vào DB. Bất cứ ai cũng có thể làm rõ điều này - tại sao tác giả nói rằng ngủ đông sẽ không theo dõi các thay đổi ở phía không sở hữu - nhưng trên thực tế ngủ đông thực hiện theo dõi?
Oleksandr Papigan

3
thác thông báo cho nhà cung cấp lưu các thực thể con ngay cả khi thực thể cha mẹ không sở hữu chúng, vì vậy nó sửa đổi quy tắc một cách hiệu quả. Nếu bạn đã có (hoặc có) mappedBy = child.field và KHÔNG có tầng thì các con trong danh sách sẽ không được lưu. Ngoài ra, nếu bạn chưa lập bản đồBy VÀ không có tầng thì Cha mẹ sở hữu mối quan hệ và nếu bạn đưa con MỚI vào danh sách và sau đó lưu Cha mẹ, nó sẽ ném ngoại lệ vì ID con mới không có sẵn được lưu trong bảng tham gia. Hy vọng rằng sẽ làm rõ mọi thứ ... :)
K.Nicholas

142

Bạn có thể tưởng tượng rằng phía sở hữu là thực thể có tham chiếu đến bên kia. Trong đoạn trích của bạn, bạn có một mối quan hệ một-một. Vì đó là mối quan hệ đối xứng , cuối cùng bạn sẽ có nếu đối tượng A có quan hệ với đối tượng B thì ngược lại cũng đúng.

Điều này có nghĩa là lưu vào đối tượng A một tham chiếu đến đối tượng B và lưu trong đối tượng B một tham chiếu đến đối tượng A sẽ là dự phòng: đó là lý do tại sao bạn chọn đối tượng nào "sở hữu" đối tượng khác có tham chiếu đến đối tượng đó.

Khi bạn có mối quan hệ một-nhiều, các đối tượng liên quan đến phần "nhiều" sẽ là phía sở hữu, nếu không, bạn sẽ phải lưu trữ nhiều tài liệu tham khảo từ một đối tượng đến vô số. Để tránh điều đó, mọi đối tượng trong lớp thứ hai sẽ có một con trỏ tới một đối tượng mà chúng tham chiếu (vì vậy chúng là phía sở hữu).

Đối với mối quan hệ nhiều-nhiều, vì dù sao bạn cũng sẽ cần một bảng ánh xạ riêng biệt, sẽ không có bất kỳ bên nào sở hữu.

Tóm lại, bên sở hữu là thực thể có tham chiếu đến bên kia.


6
Cảm ơn sự trình bày rõ ràng của bạn.
Chỉ là người học

2
Câu trả lời của tôi cũng có thể hữu ích vì lý do cho các tên 'mappedBy' và 'own own', điều gì xảy ra nếu chúng ta không xác định một bên sở hữu, GOTCHAs, hy vọng nó sẽ giúp
Đại học Angular

5
Vâng, câu trả lời chủ yếu là chính xác, tôi đoán. Nhưng đối với Hibernate ít nhất, ngay cả các mối quan hệ nhiều-nhiều cũng có một khía cạnh sở hữu. Điều này có ý nghĩa đối với hành vi cập nhật chẳng hạn. Hãy xem kỹ phần 4 ("Cập nhật lớp mô hình Hibernate") của hướng dẫn này: virpatelel.net/bloss/iêu
Pfiver 20/03/2015

11
Câu trả lời này gây nhầm lẫn nhiều hơn nó giúp. Thật tốt khi nói rằng "Bạn có thể tưởng tượng rằng bên sở hữu là thực thể có tham chiếu đến bên kia" khi trong mối quan hệ hai chiều, cả hai đối tượng Thực thể sẽ có tham chiếu với nhau? Ngoài ra, "Đối với mối quan hệ nhiều-nhiều, vì dù sao bạn cũng sẽ cần một bảng ánh xạ riêng biệt, sẽ không có bất kỳ khía cạnh sở hữu nào" hoàn toàn không chính xác: các @ManyToManymối quan hệ cũng có các mặt sở hữu. Tương tự, các @OneToManymối quan hệ có thể sử dụng các bảng tham gia và bạn vẫn phải chỉ định một bên sở hữu.
DavidS

5
Về cơ bản, đây là một câu trả lời dễ thương, cảm thấy tốt vì nó dễ hiểu hơn sự thật.
DavidS
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.