Рубрики
Без рубрики

Как изменить имя столбца общего первичного ключа @OneToOne с помощью JPA и гибернации

Узнайте, как изменить имя столбца общего первичного ключа JPA один к одному, поскольку по умолчанию Hibernate объединяет имя свойства с идентификатором сущности.

Автор оригинала: 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 является простым способом устранения этой проблемы.