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

Почему не следует использовать тип генерации АВТОМАТИЧЕСКОГО JPA с MySQL и гибернацией

Автор оригинала: Vlad Mihalcea.

Как я уже упоминал, вам никогда не следует использовать генератор идентификаторов ТАБЛИЦ, так как он неправильно масштабируется . В этом посте я покажу вам, почему вы не должны полагаться на стратегию AUTO | GenerationType , если ваше приложение Hibernate использует MySQL.

В режиме гибернации 4, если у вас было следующее сопоставление сущностей:

@Entity(name = "Post")
@Table(name = "post")
public class Post {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String title;

    public Post() {}

    public Post(String title) {
        this.title = title;
    }
}

При сохранении 3 Сообщения сущностей:

for ( int i = 1; i <= 3; i++ ) {
    entityManager.persist( 
        new Post( 
            String.format( 
                "High-Performance Java Persistence, Part %d", i
            ) 
        ) 
    );
}

Hibernate создаст следующие инструкции insert:

INSERT INTO post (title) 
VALUES ('High-Performance Java Persistence, Part 1')

INSERT INTO post (title) 
VALUES ('High-Performance Java Persistence, Part 2')

INSERT INTO post (title) 
VALUES ('High-Performance Java Persistence, Part 3')

Это здорово! Hibernate использовал столбец IDENTITY для создания идентификатора сущности, который является единственным разумным вариантом для MySQL.

Если вы запустите тот же модульный тест в Hibernate 5, вы получите следующие инструкции SQL:

SELECT next_val as id_val 
FROM hibernate_sequence FOR UPDATE

UPDATE hibernate_sequence 
SET next_val= 2 where next_val=1

SELECT next_val as id_val 
FROM hibernate_sequence FOR UPDATE

UPDATE hibernate_sequence 
SET next_val= 3 where next_val=1

SELECT next_val as id_val 
FROM hibernate_sequence FOR UPDATE

UPDATE hibernate_sequence 
SET next_val= 4 where next_val=3

INSERT INTO post (title, id) 
VALUES ('High-Performance Java Persistence, Part 1', 1)

INSERT INTO post (title, id) 
VALUES ('High-Performance Java Persistence, Part 2', 2)

INSERT INTO post (title, id) 
VALUES ('High-Performance Java Persistence, Part 3', 3)

Что только что произошло? Что ж, Hibernate выбирает генератор ТАБЛИЦЫ вместо ИДЕНТИФИКАТОРА , когда базовая база данных не поддерживает последовательности. Однако ТАБЛИЦА генератор не является хорошим выбором. Ознакомьтесь с проблемой HHH-11014 Jira для получения более подробной информации, связанной с этим изменением поведения.

Исправить это чрезвычайно просто. Вам просто нужно вместо этого использовать собственный идентификатор:

@Id
@GeneratedValue(
    strategy= GenerationType.AUTO, 
    generator="native"
)
@GenericGenerator(
    name = "native", 
    strategy = "native"
)
private Long id;

Теперь при запуске предыдущего тестового набора Hibernate вместо этого использует столбец идентификаторов:

INSERT INTO post (title) 
VALUES ('High-Performance Java Persistence, Part 1')

INSERT INTO post (title) 
VALUES ('High-Performance Java Persistence, Part 2')

INSERT INTO post (title) 
VALUES ('High-Performance Java Persistence, Part 3')

Если вы хотите использовать портативное решение, которое позволяет настраивать генератор ПОСЛЕДОВАТЕЛЬНОСТИ , сохраняя при этом возможность выбора ИДЕНТИФИКАТОРА генератора для MySQL, то ознакомьтесь с этой статьей .

Переносимость JPA-это миф! На самом деле вам необходимо знать подробные сведения о базовом поставщике JPA, если вы хотите высокопроизводительное корпоративное приложение.