Отношение JPA One-to-One создает не уникальный внешний ключ - PullRequest
3 голосов
/ 25 февраля 2020

У меня есть следующая сущность:

@Entity
public class A {

  // id, etc..

  @OneToOne
  private B b;
}

Таблица a уже существует, и когда я добавляю в нее новое поле b, hibernate выполняет следующее:

alter table a add column b_id int8
alter table a add constraint FKg76mxqt8whi8t8p4i7el95910 foreign key (b_id) references b

Как видите, столбец внешнего ключа b_id не является уникальным. Почему это так? Разве отношение «один к одному» не означает, что внешний ключ должен быть уникальным? Это также то, что я нашел в спецификации JPA для однонаправленных связей «один к одному»:

[...] Столбец внешнего ключа имеет тот же тип, что и первичный ключ таблицы B, и для него существует ограничение уникального ключа.

Чтобы это работало, я должен явно добавить аннотацию @JoinColumn(unique=true) к полю. Почему я должен сделать это явно?

1 Ответ

2 голосов
/ 25 февраля 2020

Двунаправленный @ OneToOne

Чтобы создать уникальное ограничение, необходимо создать полное двунаправленное отношение OneToOne.

Это означает, что вы должны добавить @OneToOne аннотацию к сущности Parent ( Owning ) и добавьте @OneToOne(mappedBy="...") к сущности Child .

Это создаст уникальное ограничение для вашего столбца id .

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

Официальная аннотация JavaDo c для @OneToOne содержит дополнительную информацию о дополнительных параметрах и рекомендации по двунаправленное отношение.

UPD: ссылка на hibernate спецификация о том, как обрабатывается отношение @OneToOne:

  1. Когда используя двунаправленную ассоциацию @ OneToOne , Hibernate применяет уникальное ограничение при извлечении дочерней стороны.
  2. Однонаправленная ассоциация следует семантике внешнего ключа реляционной базы данных, причем клиентская сторона владеет отношением.

В вашем случае

Это означает, что в вашей модели B сущности вы должны добавить поле с вашей сущностью A и аннотировать его с помощью @OneToOne(mappedBy="b"), чтобы установить вашу связь двунаправленный и полный, ограничивающий доступ к одному Родителю и создающий уникальное ограничение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...