GenerationType.SEQUENCE генерирует идентификаторы, которые уже существуют

#spring #hibernate #jpa #spring-boot

#spring #спящий режим #jpa #spring-boot

Вопрос:

У меня есть приложение Spring boot, которое уже работает онлайн в течение нескольких месяцев без каких-либо проблем до сегодняшнего дня. У меня есть объект с типом генерации идентификатора sequence:

 @Entity
@ComponentScan
public class MyEntity {
    /**
     * 
     */
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;
}
  

С сегодняшнего дня я получаю ошибки при создании и сохранении нового объекта:

 Unique index or primary key violation: "PRIMARY_KEY_D92 ON PUBLIC.MyEntity(ID) VALUES (3713, 250)"; SQL statement:
  

Каждый раз, когда возникает эта ошибка, сгенерированный идентификатор (в данном случае 3713) уже существует в базе данных. Итак, почему вдруг GenerationType.SEQUENCE генерирует идентификаторы, которые уже существуют?

Редактировать

Я использую базу данных H2 версии 1.4.191

Ответ №1:

Я столкнулся с этой проблемой с гибернацией, но у нас были явные @SequenceGenerator аннотации. Проблема в том, что SequenceGenerator по умолчанию в JPA имеет allocationSize значение 50, где последовательность базы данных по умолчанию увеличивается на 1. Эти два значения должны быть одинаковыми. Одним из решений является определение вашего SequenceGenerator и явное задание этого allocationSize.

 @SequenceGenerator(name = "my_entity_gen", sequenceName = "my_entity_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "my_entity_gen")
  

Генераторы должны быть уникальными, если вы не хотите, чтобы две таблицы использовали их совместно.

Другим решением является использование другой стратегии генерации.

 @GeneratedValue(strategy = GenerationType.IDENTITY)
  

Это работает, если база данных уже знает, что запрашивать последовательность при вставке, как они обычно делают, если вы явно не создали последовательность после таблицы.

Первый подход будет запускать два запроса к базе данных для каждой вставки, поэтому он почти наверняка менее эффективен.

Комментарии:

1. Привет. Если я изменю его на GenerationType.IDENTITY , я получу только нулевые значения в качестве идентификатора: NULL not allowed for column "ID"

2. Вы пробовали другой подход? Другой способ заставить его использовать последовательность перед каждой вставкой — это установить hibernate.id.optimizer.pooled.preferred свойство в вашем persistence.xml на none . Чувствителен к регистру. Это свойство может быть недоступно до перехода в спящий режим 5. Вы не указали свою версию или базу данных.