Избегайте дублирования первичных ключей после инициализации базы данных в spring-boot 2 - PullRequest
0 голосов
/ 01 марта 2019

Стратегия @GeneratedValue по умолчанию, используемая для работы в веб-приложении с пружинной загрузкой 1.5, без повторяющихся конфликтов идентификаторов любого типа

... с использованием простой сущности, такой как эта

// in my/package/Car.java
// ...
@Entity
public class Car {
    private long id;
    private String company;
    private String model;

    @Id
    @GeneratedValue
    public long getId() {
        return id;
    }

    // ... more getters and setters
}

... и инициализация БД при запуске с помощью

# in src/main/resources/import.sql
insert into car values (1, 'Tesla', 'Roadster');

..., а затем вставка другой машины с

Car c = new Car();
c.setCompany("Ford");
c.setModel("Pinto");
entityManager.persist(c);
entityManager.flush();

// expect no issue inserting, and a valid ID
log.info("Assigned ID is " + c.getId());

..., используемой для полученияновый Car с идентификатором 2.Я действительно не забочусь о сгенерированном идентификаторе, пока нет конфликта.Однако этот же код теперь выдает следующее исключение:

org.hsqldb.HsqlException: integrity constraint violation: unique constraint or index violation; SYS_PK_10095 table: CAR (база данных - HSQL, и я бы предпочел не заменять ее)

... потому что генерация последовательности по умолчанию в hibernate 5.2 теперь не учитывает существующие вставки.

Какие у меня есть возможные обходные пути, чтобы разрешить инициализацию базы данных через import.sql?Я знаю, что могу

  • использовать очень большие идентификаторы во время инициализации (но это просто удар по банке в будущем, а не реальное решение: в конце концов последовательность будет догонять и ломать вещи)
  • написать свой собственный генератор последовательностей (но должен быть гораздо более простой способ инициализации БД!)
  • использовать старое поколение последовательностей (но опять же, почему они изменили его, если не было никакого преимуществадля этого разработчики hibernate наверняка имели в виду какой-то лучший способ инициализации!).
  • каким-то образом задают начальное значение для новых идентификаторов (как мне сделать это безопасным способом? есть ли свойствочто может войти в мой application.properties, чтобы сохранить это централизованное?)

Я хочу использовать это в контексте весеннего загрузочного веб-приложения, и сделать его максимально простым и близким к лучшим практикамнасколько это возможно.Предложения?

1 Ответ

0 голосов
/ 01 марта 2019

С версии 5 SEQUENCE используется вместо IDENTITY для генерации идентификатора. Миграция из Hibernate 4 на 5

Что случилось?

Вы вставили запись с ID 1, используя скрипт.Последовательность остается на 1. Он хочет вставить 1, что вызывает уникальное нарушение PK.

Решение

Не использовать автоматический тип генерации.Используйте IDENTITY.Затем вставка записей по сценарию, IDENTITY будет автоматически увеличена.Также вам не нужно вводить значение ID:

 DECLARE temp_id INTEGER;
 INSERT INTO CUSTOMERS VALUES (DEFAULT, firstname, lastname, CURRENT_TIMESTAMP);
 SET temp_id = IDENTITY();
 INSERT INTO ADDRESSES VALUES (DEFAULT, temp_id, address);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...