Что такое "собственная сторона" в сопоставлении ORM?

Что означает владеющая сторона? Что такое объяснение с некоторыми примерами сопоставления (от одного до многих, от одного до одного, от нескольких до одного)?

Следующий текст является выдержкой из описания @OneToOne в документации Java EE 6. Вы можете увидеть концепцию владеющая сторона.

Определяет однозначную связь с другой объект, который имеет один к одному множественность. Это не нормально необходимо указать связанные целевой объект явно, поскольку он может обычно выводятся из типа объект, на который делается ссылка. Если отношение является двунаправленным, не владеющая сторона должна использовать mappedBy элемент аннотации OneToOne к укажите поле отношений или собственность владельца.

Ответ 1

Вы можете себе представить, что владеющая сторона - это сущность, которая имеет ссылку на другую. В вашей отрывке у вас есть отношения "один к одному". Поскольку это симметричное отношение, вы получите в результате, что если объект A связан с объектом B, то и наоборот. True.

Это означает, что сохранение в объекте A ссылки на объект B и сохранение в объекте B ссылки на объект A будет избыточным: почему вы выбираете, какой объект "владеет" другим, имеющим ссылку на него.

Когда у вас есть отношения "один ко многим", объекты, связанные со "большой" частью, будут принадлежать стороне, иначе вам придется хранить много ссылок от одного объекта до множества. Чтобы этого избежать, каждый объект во втором классе будет иметь указатель на тот, на который они ссылаются (так что они являются собственностью).

Для отношения "многие-ко-многим", поскольку в любом случае вам понадобится отдельная таблица сопоставления, не будет никакой собственной стороны.

В заключение владеющая сторона является объектом, который имеет ссылку на другую.

Ответ 2

Почему необходимо понятие принадлежности:

Идея принадлежащей стороне двунаправленного отношения возникает из-за того, что в реляционных базах данных нет двунаправленных отношений, например, в случае объектов. В базах данных мы имеем только однонаправленные отношения - внешние ключи.

В чем причина имени "владеющая сторона"?

Собственная сторона отношения, отслеживаемого Hibernate, является стороной отношения, которое владеет внешним ключом в базе данных.

В чем проблема, которую решает идея владения стороной?

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

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

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

С точки зрения OO это сопоставление определяет не одно двунаправленное отношение, а два отдельных однонаправленных отношения.

Отображение создало бы не только таблицы 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. Hibernate должен отслеживать только другую сторону отношения IdDocument.person, и для этого мы добавляем mappedBy:

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

Что это значит: mappedBy?

Это означает что-то вроде: "модификации на этой стороне отношения уже отображаются с помощьюс другой стороны отношения IdDocument.person, поэтому нет необходимости отслеживайте его здесь отдельно в дополнительной таблице.

Есть ли какие-либо GOTCHA, последствия?

Использование mappedBy. Если мы вызываем только person.getDocuments().add(document), внешний ключ в ID_DOCUMENTS будет привязан к NOT к новому документу, потому что это не принадлежность/отслеживаемая сторона отношения!

Чтобы связать документ с новым человеком, вам нужно явно вызвать document.setPerson(person), потому что это сторона владельца.

При использовании mappedBy разработчик должен знать, что является владельцем, и обновлять правильную сторону отношения, чтобы вызвать постоянство нового отношения в базе данных.