Что такое «сторона владения» в отображении ORM? - PullRequest
112 голосов
/ 01 мая 2010

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

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

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

Ответы [ 2 ]

157 голосов
/ 12 января 2014

Почему необходимо понятие «владеющая сторона»:

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

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

Собственная сторона отношения, отслеживаемого 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 создает два однонаправленных отношения (внешнего ключа) в базе данных для реализации one двунаправленного отношения объекта.

Как понятие «сторона владения» решает проблему:

Во многих случаях нам нужен только внешний ключ в таблице ID_DOCUMENTS в направлении PERSONS и дополнительная таблица ассоциации.

Чтобы решить эту проблему, нам нужно настроить Hibernate, чтобы перестать отслеживать изменения в отношении Person.idDocuments. Hibernate должен отслеживать только другую сторону отношения IdDocument.person, и для этого мы добавляем mappedBy :

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

Что значит mappedBy?

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

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

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

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

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

130 голосов
/ 01 мая 2010

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

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

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

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

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

...