Hibernate / JPA ManyToOne против OneToMany
В настоящее время я читаю документацию Hibernate относительно ассоциаций сущностей, и я немного затрудняюсь выяснить некоторые вещи. Это должно быть сделано по существу с различием между ManyToOne
и OneToMany
. Хотя я использовал их в реальных проектах, я не могу полностью понять разницу между ними. Насколько я понимаю, если таблица / сущность имеет ассоциацию ManyToOne
с другой, то ассоциация должна быть с другой стороны OneToMany
. Итак, как нам решить, какой из них выбрать на основе конкретного случая и как он влияет на базу данных / запросы / результаты? Есть ли повсюду хороший пример?
PS: Я считаю, что это было бы полезно из-за его релевантности в вопросе, если бы кто-то мог, кроме того, объяснить, какова точка владельца ассоциации и разница между двунаправленной и однонаправленной ассоциацией.
- Использование дженериков в репозиториях Spring Data JPA
- setMaxResults для annotations Spring-Data-JPA?
- Где ConfigurationGenerateSchemaCreationScript () переместился в Hibernate 5
- JAXB Отображение циклических ссылок на XML
- Как правильно выразить JPQL «join fetch» с предложением «where» как JPA 2 CriteriaQuery?
- Объединение двух элементов таблицы в Spring Data JPA
- JPA: ПРИСОЕДИНЯЙТЕСЬ в JPQL
- Выражение конструктора JPQL - org.hibernate.hql.ast.QuerySyntaxException: таблица не отображается
- inverse = true в аннотациях JPA
- JPA 2.0 аннотация @OrderColumn в Hibernate 3.5
- Получение соединения с базой данных в чистой настройке JPA
- Установка значений по умолчанию для столбцов в JPA
- Указание индекса (не-уникальный ключ) с использованием JPA
Предположим, что у вас есть заказ и заказ. Вы можете выбрать однонаправленную OneToMany между Order и OrderLine (у Order будет коллекция OrderLines). Или вы можете выбрать связь ManyToOne между OrderLine и Order (OrderLine будет иметь ссылку на свой Ордер). Или вы можете выбрать оба варианта, и в этом случае ассоциация становится двунаправленной ассоциацией OneToMany / ManyToOne.
Решение, которое вы выбираете, в основном зависит от ситуации и от уровня связи между объектами. Например, если у пользователя, компании, у провайдера есть много адресов, имеет смысл иметь однонаправленную связь между каждым из них и адресом, а адрес не знать об их владельце.
Предположим, у вас есть Пользователь и Сообщение, где у пользователя могут быть тысячи сообщений, может иметь смысл моделировать его только как ManyToOne от Message to User, потому что вы редко будете запрашивать все сообщения пользователя в любом случае. Связь может быть сделана двунаправленной только для помощи с запросами, поскольку, поскольку запросы JPQL соединяются между объектами путем навигации по их ассоциациям.
В двунаправленной связи вы можете оказаться в ситуации, когда график объектов несовместим. Например, Order A будет иметь пустой набор OrderLines, но некоторые OrderLines будут иметь ссылку на заказ A. JPA налагает обязательство всегда иметь одну сторону ассоциации, являющуюся стороной владельца, а другая сторона является обратной стороной. Обратная сторона игнорируется JPA. Сторона владельца – это сторона, которая решает, какое отношение существует. В двунаправленной ассоциации OneToMany сторона владельца должна быть большой стороной. Таким образом, в предыдущем примере сторона владельца была бы OrderLine, и JPA сохраняла бы связь между строками и порядком A, поскольку строки имеют ссылку на A.
Такая ассоциация будет отображаться следующим образом:
в порядке :
@OneToMany(mappedBy = "parentOrder") // mappedBy indicates that this side is the // inverse side, and that the mapping is defined by the attribute parentOrder // at the other side of the association. private Set lines;
в OrderLine:
@ManyToOne private Order parentOrder;
Кроме того, если @ManytoOne
сторона как владелец потребует только n + 1 запросов при сохранении ассоциаций. Где n – количество ассоциаций (много сторон).
Принимая во внимание, что @OneToMany
как владелец, при вставке родительского объекта (с одной стороны) с ассоциациями (много сторон) приведет к 2 * N + 1 запросам. В котором один запрос был бы для вставки ассоциации, а другой запрос – для обновления внешнего ключа в связанном объекте.