Стратегия @GeneratedValue по умолчанию, используемая для работы в веб-приложении spring boot 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. Меня не очень волнует сгенерированный ID, пока нет конфликта. Однако этот же код теперь выдает следующее исключение:
org.hsqldb.HsqlException: integrity constraint violation: unique constraint or index violation; SYS_PK_10095 table: CAR
(БД - это HSQL, и мне бы не хотелось ее заменять)
... потому что генерация последовательности по умолчанию в спящем режиме 5.2 теперь не учитывает существующие вставки.
Каковы мои возможные обходные пути, чтобы по-прежнему разрешать инициализацию базы данных через import.sql? я знаю что могу
application.properties, чтобы сохранить это централизованно?)Я хочу использовать это в контексте веб-приложения с весенней загрузкой и сделать его максимально простым и близким к лучшим практикам. Предложения?
@MatthiasLauber да, в этом проблема. Однако мне нужно иметь возможность вставлять операторы SQL, потому что в противном случае я не могу включать отношения (которые требуют, чтобы идентификатор соответствовал значению внешнего ключа). Как бы вы инициализировали БД с идентификаторами в противном случае? Альтернативный способ инициализации идентификатора был бы допустимым ответом.
Вы пользуетесь Flyway? Там вы пишете схему SQL для своих таблиц. Вы можете определить последовательность и указать своим таблицам использовать следующее значение последовательности для генерации идентификатора и вставить последовательность в свои объекты Spring.
@MatthiasLauber Я не использую Flyway и хотел бы свести к минимуму зависимости. Тем не менее, это кажется рабочим решением: спасибо.
Начиная с версии 5 вместо IDENTITY для генерации идентификатора используется SEQUENCE. Миграция с Hibernate 4 на 5
Что случилось?
Вы вставили запись с ID 1 с помощью скрипта. Последовательность остается равной 1. Она хочет вставить 1, что вызывает уникальное нарушение PK.
Решение
Не используйте автоматический тип генерации. Используйте ИДЕНТИЧНОСТЬ. Затем при вставке записей скриптом IDENTITY будет автоматически увеличиваться. Также вам не нужно вставлять значение идентификатора:
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);
Да, я уже проверил, что этот дублирующийся первичный ключ был проблемой (если идентификаторы начинаются, скажем, с 10 в insert.sql, проблем не обнаружено; это пункт № 1 моего списка обходных путей, который, очевидно, не сработает, учитывая достаточно времени). Использование IDENTITY кажется возможным, однако я не понимаю, почему мне не нужно вставлять идентификаторы: как еще я могу добавить отношения через import.sql? Есть ли другой способ инициализировать БД без идентификаторов, но с отношениями «один ко многим» и «многие ко многим»?
последнее вставленное значение в столбец идентификации для соединения доступно с помощью функции IDENTITY()
Ссылка не работает; Я нашел это: hsqldb.org/doc/guide/builtinfunctions-chapt.html; однако я до сих пор не знаю, как использовать это в файле import.sql, чтобы, скажем, указать, что Car 1 управляется Person 2, предполагая отношение Person_Car, которое принимает car_id и person_id
Привет, я не уверен, правильно ли я понял ваш вопрос, но у меня была аналогичная проблема, и ошибка заключалась в том, что я вставлял элемент с помощью инструкции SQl. В этом заявлении для идентификатора установлено фиксированное значение, но, насколько мне известно, Spring управляет вашим GeneratedValue, и он не смог распознать установленный вручную идентификатор. Поэтому, когда вы вставляете элемент с использованием контекста Spring, последовательность GeneratedValue начинается с 1 и выдает ошибку, поскольку идентификатор уже существует.