Почему необходимо понятие стороны собственности:
Идея владения стороны двунаправленного отношения исходит из того факта, что в реляционных базах данных нет двунаправленных отношений, как в случае с объектами. В базах данных у нас только однонаправленные отношения - внешние ключи.
В чем причина названия «сторона собственника»?
Собственная сторона отношения, отслеживаемая 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;
}
С объектно-ориентированной точки зрения это отображение определяет не одно двунаправленное отношение, а два отдельных однонаправленных отношения.
Отображение создаст не только таблицы 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
будет НЕ быть связаны с новым документом, поскольку это не владеющая / гусеничная стороны отношения!
Чтобы связать документ с новым человеком, вам нужно явно вызвать document.setPerson(person)
, потому что это сторона-владелец отношения .
При использовании mappedBy разработчик обязан знать, что является стороной-владельцем, и обновлять правильную сторону отношения, чтобы вызвать сохранение нового отношения в базе данных.