Яка "власна сторона" в картографуванні ORM?


128

Що саме означає сторона володіння ? Яке пояснення з деякими прикладами картографування ( один до багатьох, один до одного, багато до одного )?

Наступний текст - уривок із опису документації @OneToOne в Java EE 6. Ви можете побачити сторону концепції, що є в ній.

Визначає однозначну асоціацію до іншої сутності, яка має множинність один на один. Зазвичай не потрібно чітко вказувати асоційований цільовий об'єкт, оскільки він, як правило, може бути виведений з типу об'єкта, на який посилається. Якщо взаємозв'язок є двонаправленим, сторона , яка не володіє, повинна використовувати елемент mappedBy анотації OneToOne для визначення поля відносин або властивості сторони, що володіє.



5
Я загубився, поки не прочитав це: javacodegeeks.com/2013/04/…
darga33

2
Таблиця БД із стовпцем із зовнішнім ключем розглядається як сторона, що володіє. Отже, суб'єкт господарювання, що представляє таблицю БД, є власником (власником) цього відношення. Не обов'язково, але в більшості випадків на власниках буде анотація @JoinColumn.
Діабло

Відповіді:


202

Чому потрібне поняття власної сторони:

Ідея власного боку двонаправленого відношення походить від того, що в реляційних базах даних немає двонаправлених відносин, як у випадку з об'єктами. У базах даних ми маємо лише однонаправлені відносини - зовнішні ключі.

У чому причина назви "володіння стороною"?

Сторона, що має відношення, відстежується в сплячому режимі, - це сторона відносини, якій належить зовнішній ключ у базі даних.

Яка проблема, яку вирішує поняття володіння стороною?

Візьмемо приклад двох сутностей, відображених без декларування власного боку:

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

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

З точки зору ОО, це відображення визначає не одне двонаправлене відношення, а два окремі однонаправлені відносини.

Відображення створило б не тільки таблиці PERSONSта ID_DOCUMENTS, але й створило б третю таблицю асоціацій 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)
)

Зверніть увагу , що первинний ключ pkна ID_DOCUMENTSтільки. У цьому випадку Hibernate відстежує обидві сторони відношення незалежно: Якщо ви додаєте документ у відношення Person.idDocuments, він вставляє запис у таблицю асоціацій PERSON_ID_DOCUMENTS.

З іншого боку, якщо ми зателефонуємо idDocument.setPerson(person), ми змінимо іноземний ключ person_id на столі ID_DOCUMENTS. Hibernate створює два однонаправлені (зовнішні ключові) відносини в базі даних, щоб реалізувати одне двостороннє відношення об'єкта.

Як поняття володіння стороною вирішує проблему:

Багато разів то , що ми хочемо тільки зовнішній ключ на столі в ID_DOCUMENTSстороні PERSONSі додаткова таблиця асоціації.

Щоб вирішити це, нам потрібно налаштувати Hibernate, щоб припинити відстежувати модифікації відношення Person.idDocuments. Спящий режим повинен відслідковувати лише іншу сторону відносин IdDocument.person, і для цього ми додаємо mappedBy :

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

Що означає відображеноBy?

Це означає що - щось на кшталт: «модифікації на цій стороні відносин вже Підключення До іншій стороні відносин IdDocument.person, тому немає необхідності відстежувати його тут окремо в додатковій таблиці.»

Чи є якісь ГОТЧИ, наслідки?

Використання mappedBy , якщо ми тільки називаємо person.getDocuments().add(document), зовнішній ключ в ID_DOCUMENTSбуде НЕ бути пов'язані з новим документом, оскільки це не володіє / гусенична боку відносини!

Щоб зв’язати документ з новою особою, вам потрібно чітко зателефонувати document.setPerson(person), оскільки це є власною стороною відносин.

Використовуючи mappedBy , розробник несе обов'язок знати, що є власником, і оновлювати правильну сторону співвідношення, щоб викликати збереження нового відношення в базі даних.


17
Найкраща відповідь, яку я вважаю, пояснює вчення "mappedBy" + "перевернутеBy".
Курт Чжун

1
Дякуємо, що вказали відображення та причину концепції.
Mohnish

1
Я не знаю, чи все змінилося, але в режимі Hibernate 5.0.9.Закінчення, якщо я "лише дзвоню person.getDocuments().add(document)", сплячка оновлює зовнішній ключ ID_DOCUMENTS.
К.Ніколас

1
@Karl Nicholas, привіт, погоджуюсь з вами, у нас атрибут каскаду в @OneToManyанотації, який можна встановити на PERSIST, в цьому випадку сплячий режим збереже всі пов'язані об'єкти в БД. Хто-небудь може уточнити це - чому автор каже, що сплячий не буде відслідковувати зміни з боку, що не є власником, - а насправді сплячий здійснює відстеження?
Олександр Папченко

3
каскад повідомляє провайдеру зберегти дочірні об'єкти, навіть якщо материнська сутність не володіє ними, тому вона фактично змінює правило. Якщо у вас був (або у вас) mappedBy = child.field і не було каскаду, то діти зі списку не збереглися. Крім того, якщо ви не мали mappedBy AND не мали каскаду, тоді Батько є власником відносин, і якщо ви внесете НОВИХ дітей у список, а потім збережіть батьків, це викине виняток, оскільки нові ідентифікатори дітей не доступні зберегти в таблиці приєднання. Сподіваюсь, що все з'ясовує ... :)
К.Ніколас

142

Ви можете уявити, що сторона, що володіє, - це сутність, яка має посилання на іншу. У своєму уривку у вас стосунки один на один. Оскільки це симетричне відношення, то в кінцевому підсумку ви будете мати те, що якщо об’єкт A знаходиться у відношенні до об'єкта B, то і навпаки вірно.

Це означає, що збереження в об'єкті A посилання на об'єкт B і збереження в об'єкті B посилання на об'єкт A буде зайвим: саме тому ви вибираєте, який об'єкт "володіє" іншим, на який має посилання.

Коли у вас є взаємозв'язок "один на багато", об'єкти, пов'язані з частиною "багато", будуть стороною власності, інакше вам доведеться зберігати багато посилань від одного об'єкта до безлічі. Щоб уникнути цього, кожен об'єкт другого класу матиме вказівник на єдиний, на який вони посилаються (тому вони є власником).

Для відносин "багато-до-багатьох", оскільки вам все одно знадобиться окрема таблиця відображення, не буде жодної сторони.

На закінчення, власником є суб'єкт господарювання, який має посилання на іншу.


6
Дякую за роз’яснення.
Просто учень

2
це може допомогти побачити внизу, а також мою відповідь з причин імен "mappedBy" та "володіння стороною", що станеться, якщо ми не визначимо власну сторону, GOTCHAs, сподіваюся, що це допоможе
Angular University

5
Що ж, відповідь, як правило, правильна. Але для сплячого принаймні, навіть багато-багато-багато стосунків мають свою сторону. Це може вплинути, наприклад, на поведінку оновлення. Уважно
сплячки

11
Ця відповідь бентежить більше, ніж допомагає. Яке добре сказати, що "Ви можете уявити, що сторона, що володіє, є сутністю, яка має посилання на іншу", коли в двосторонніх відносинах обидва об'єкта Entity матимуть посилання один на одного? Крім того, "Для відносин між багатьма, оскільки у будь-якому випадку вам буде потрібна окрема таблиця зіставлення, не буде жодної сторони, що володіє", просто невірно: @ManyToManyвідносини мають і свої сторони. Так само @OneToManyвідносини можуть використовувати таблиці приєднання, і вам все одно потрібно вказати сторону, що володіє.
DavidS

5
В основному, це мила відповідь, яка почуває себе добре, тому що це легше зрозуміти, ніж правда.
DavidS
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.