Автор оригинала: Vlad Mihalcea.
Вступление
В этой статье мы рассмотрим, как вы можете изменить имя столбца @OneToOne общий первичный ключ при использовании JPA и Hibernate. Это была повторяющаяся тема, когда отвечал на вопросы о спящем режиме или во время моего Высокопроизводительного обучения сохраняемости Java .
Как уже объяснялось ранее , связь таблиц базы данных “один к одному” требует, чтобы Первичный ключ был общим для родительской и дочерних таблиц.
К сожалению, простое добавление аннотации JPA @OneToOne в дочернюю сущность не отображает истинную связь таблицы “один к одному”, поскольку будет использоваться отдельный столбец внешнего ключа. Только при добавлении аннотации @MapsId ассоциация JPA “один к одному” сопоставляется с реальным отношением таблицы “один к одному”.
Как изменить @OneToOne имя столбца общего первичного ключа с помощью JPA и гибернации @vlad_mihalcea https://t.co/BoQsxJ6Lvm pic.twitter.com/kP5hgBRw1b
Модель предметной области
Давайте предположим, что мы используем следующие Сообщения и Сведения о сообщениях сущности:
Сущность Post является родительской, в то время как Сведения о записи является дочерней сущностью, и связанный с ней Первичный ключ также является внешним ключом к Первичному ключу родительской таблицы.
Объект Post довольно просто сопоставить, так как он не содержит никаких ассоциаций:
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
//Getters and setters omitted for brevity
}
Сведения о публикации могут быть сопоставлены следующим образом:
@Entity(name = "PostDetails")
@Table(name = "post_details")
public class PostDetails {
@Id
private Long id;
@Column(name = "created_on")
private Date createdOn;
@Column(name = "created_by")
private String createdBy;
@OneToOne(fetch = FetchType.LAZY)
@MapsId
private Post post;
public PostDetails() {}
public PostDetails(String createdBy) {
createdOn = new Date();
this.createdBy = createdBy;
}
//Getters and setters omitted for brevity
}
Обратите внимание, что мы используем FetchType.ЛЕНИВЫЙ явно, так как по умолчанию JPA использует Fetchtype.ЖАЖДЕТ для @OneToOne и @ManyToOne ассоциаций, и это очень плохо сказывается на производительности .
При создании схемы с помощью инструмента hbm2ddl или при создании схемы вручную и управлении ею с помощью Flyway Hibernate ожидает следующую структуру таблиц базы данных:
Обратите внимание, что имя столбца первичного ключа называется post_id в таблице post_details , и это не очень приятно, так как имя столбца первичного ключа называется id в таблице post .
@JoinColumn спешит на помощь
Чтобы устранить эту проблему, нам просто нужно добавить @JoinColumn аннотацию к @OneToOne ассоциации в Сведения о публикации сущности:
@OneToOne @MapsId @JoinColumn(name = "id") private Post post;
Таким образом, Hibernate либо создаст, либо ожидает следующие таблицы базы данных:
Потрясающе, правда?
Вывод
Немного жаль, что по умолчанию в аннотации @MapsId не используется имя идентификатора сущности, соответствующее столбцу первичного ключа базовой таблицы. Однако использование аннотации @JoinColumn является простым способом устранения этой проблемы.