JPA - разница в использовании свойства mappedBy для определения объекта-владельца

В чем именно разница в следующих двух декларациях

B является владельцем

@Entity
class A {
   @Id int id;

   @OneToOne
   B b;
}

@Entity
class B {
   @Id int id;

   @OneToOne(mappedBy="b")
   A a;
}

А владеющая сторона

@Entity
class A {
   @Id int id;

   @OneToOne(mappedBy="a")
   B b;
}

@Entity
class B {
   @Id int id;

   @OneToOne
   A a;
}

Думая об этом в «нормальном SQL» я думаю, что это то же самое, что иметь две таблицы, каждая из которых имеет внешний ключ другой таблицы. Однако я не понимаю, каков эффект определения того, какая сущность является стороной-владельцем, т.е. с использованием «mappedBy»; имущество. Чего это действительно добивается, поскольку я не верю, что в нормальном SQL есть эквивалент.

 Piotr Nowicki10 июн. 2012 г., 14:31
Вы проверяли, что в обоих случаях таблицы A и B будут иметь FK друг к другу?

Ответы на вопрос(4)

которую JPA считает знать, существует ассоциация или нет. Предположим, вы идете со своим первым примером. Сторона-владелец - это сторона, где нет атрибута mappedBy. Таким образом, владельцем является A, а не B.

Это означает, что если у вас есть A и B в базе данных, и вы делаете

A a = em.find(A.class, aId);
B b = em.find(B.class, bId);
a.setB(b);

JPA сохранит ассоциацию (то есть он сохранит идентификатор B в столбце соединения таблицы A).

Но если вы делаете

A a = em.find(A.class, aId);
B b = em.find(B.class, bId);
b.setA(a);

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

A таблица будет иметь 2 столбцаid а такжеb_id,B таблица будет иметь один столбец,id, Это делаетA владеющая сторона.

Во втором примереB владеющая сторона.B имеет две колонки,id а такжеa_id. A будет иметь один столбец,id.

И это разница :-)

Решение Вопроса

Спецификация JPA 2.0, раздел 2.9, пишет:

Relationships may be bidirectional or unidirectional. A bidirectional relationship has both an owning side and an inverse (non-owning) side. A unidirectional relationship has only an owning side. The owning side of a relationship determines the updates to the relationship in the database, as described in section 3.2.4.

The following rules apply to bidirectional relationships:

The inverse side of a bidirectional relationship must refer to its owning side by use of the mappedBy element of the OneToOne, OneToMany, or ManyToMany annotation. The mappedBy element designates the property or field in the entity that is the owner of the relationship. The many side of one-to-many / many-to-one bidirectional relationships must be the owning side, hence the mappedBy element cannot be specified on the ManyToOne annotation. For one-to-one bidirectional relationships, the owning side corresponds to the side that contains the corresponding foreign key. For many-to-many bidirectional relationships either side may be the owning side.

Соответствующие части раздела 3.2.4:

The state of persistent entities is synchronized to the database at transaction commit. This synchronization involving writing to the database any updates to persistent entities and their relationships as specified above.

а также

Bidirectional relationships between managed entities will be persisted based on references held by the owning side of the relationship. It is the developer’s responsibility to keep the in-memory references held on the owning side and those held on the inverse side consistent with each other when they change. In the case of unidirectional one-to-one and one-to-many relationships, it is the developer’s responsibility to insure that the semantics of the relationships are adhered to.

It is particularly important to ensure that changes to the inverse side of a relationship result in appropriate updates on the owning side, so as to ensure the changes are not lost when they are synchronized to the database.

вы ошибаетесь в том, какая сторона является вашей в ваших примерах. Под «владением» мы подразумеваем владение отношениями с точки зрения ОО, на практике это довольно часто оказывается противоположностью того, как оно будет или будет сгенерировано в БД, если кто-то использует rdbm в качестве поставщика постоянства.

В нормальных условиях модель ОО дает понять, какие стороны являются собственниками. Например, у ордера есть строки заказа. Если мы удалим Заказ, все Строки Заказа должны быть удалены. Если мы удалим OrderLine, ордер, возможно, все еще имеет право на существование. Следовательно, Орден является собственником.

Более конкретный и превосходный пример, касающийся влияния той стороны, которая является стороной-владельцем, приведен в ответе @JB Nizet.

Согласно разделу 2.9JPA 2.0 спецификация:

For one-to-one bidirectional relationships, the owning side corresponds to the side that contains the corresponding foreign key.

Но в том же разделе мы также имеем:

In addition, this specification also requires support for the following alternative mapping strategies: [..] The mapping of unidirectional and bidirectional one-to-one relationships, bidirectional many-to-one/one-to-many relationships, and unidirectional many-to-one relationships by means of join table mappings.

Немного дальше в том же разделе, он продолжает:

Additional mapping annotations (e.g., column and table mapping annotations) may be speci- fied to override or further refine the default mappings and mapping strategies described in Section 2.10. Some implementations make use of that to allow the FK of a birectional OneToOne to be in the target table.

Чтобы прочитать о некоторых стратегиях решения этого сценария, см .:Почти хорошее объяснение

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

 10 июн. 2012 г., 15:36
Нет, JPA указывает, что сторона владения двунаправленной ассоциацией OneToOne является той, которая содержит внешний ключ. То же самое для двунаправленного OneToMany.
 10 июн. 2012 г., 16:22
"и его можно использовать в отображении OneToOne, в котором первичный ключ ссылающегося объекта используется в качестве внешнего ключа для ссылочного объекта".docs.oracle.com/javaee/6/api/javax/persistence/… , Ситуацияjust не появляется так часто.
 10 июн. 2012 г., 16:43
Да. Я стою исправлено. Я могу сделать это в EclipseLink, и я полностью пропустил это не в соответствии с окончательной спецификацией 2.0. Формулировка в спецификации вроде заставляет меня чувствовать, что реализация (и) нарушает спецификацию. Я обновлю свой ответ, чтобы избавиться от лжи. Спасибо.
 10 июн. 2012 г., 16:25
И это ничего не меняет. В этом случае столбец первичного ключа является столбцом соединения (отсюда и имя PrimaryKeyJoinColumn), а сущность, содержащая эту аннотацию, и, следовательно, столбец соединения, является стороной-владельцем. Прочитайте ответ @ meriton, содержащий этот отрывок из спецификации JPA: «Для двунаправленных отношений« один к одному »сторона-владелец соответствует стороне, которая содержит соответствующий внешний ключ».

Ваш ответ на вопрос