2013-09-24 2 views
7

Проблема ОбзорJPA 2 @SequenceGenerator @GeneratedValue производит уникальное нарушение ограничения

На первый взгляд случайные моменты времени, мы получаем исключение «PostgreSQL дубликат ключа нарушает ограничение уникальности». Я действительно думаю, что знаю, что такое наша проблема », но я не хочу вносить изменения в код, не имея воспроизводимого тестового примера. Но так как мы не смогли воспроизвести его ни в какой другой среде, кроме случайного производства, я прошу помощи от SO.

В этом проекте имеется несколько баз данных постгрейса и последовательность первичных ключей, настроенная для каждой таблицы в каждой базе данных. Эти последовательности создаются следующим образом:

create sequence PERSONS_SEQ; 
create sequence VISITS_SEQ; 
etc... 

Мы используем эти последовательности для генерации первичных ключей сущностей, как это:

@Entity 
@Table(name = "visits") 
public class Visit { 
    @Id 
    @Column(name = "id") 
    @SequenceGenerator(name = "seq", sequenceName = "visits_seq") 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq") 
    private int id; 
    ... 
} 

@Entity 
@Table(name = "person") 
public class Person { 
    @Id 
    @Column(name = "id") 
    @SequenceGenerator(name = "seq", sequenceName = "persons_seq") 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq") 
    private int id; 
    ... 
} 

Анализ

Я думаю, что распознают 2 проблемы с эта конфигурация:

1) Оба генератора @SequenceGenerator указывают один и тот же атрибут имени, даже если они Предполагается, что они должны отображаться в разных последовательностях базы данных.

2) Атрибут распределения @SequenceGenerator allocSize по умолчанию равен 50 (мы используем hibernate как поставщик JPA), поэтому я думаю, что синтаксис create sequence должен указывать, в какой степени последовательность должна увеличиваться, в частности, на 50, чтобы соответствовать allocSize.

Исходя из этого предположения, я думаю, что код должен быть изменен, чтобы что-то вроде этого:

create sequence PERSONS_SEQ increment by 50; 
create sequence VISITS_SEQ increment by 50; 
etc... 

@Entity 
@Table(name = "visits") 
public class Visit { 
    @Id 
    @Column(name = "id") 
    @SequenceGenerator(name = "visits_seq", sequenceName = "visits_seq") 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "visits_seq") 
    private int id; 
    ... 
} 

@Entity 
@Table(name = "person") 
public class Person { 
    @Id 
    @Column(name = "id") 
    @SequenceGenerator(name = "persons_seq", sequenceName = "persons_seq") 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "persons_seq") 
    private int id; 
    ... 
} 

я бы просто проверить это, а не задавать вопрос о SO, но опять же, мы не смогли воспроизведите эту проблему производства в любых других средах. И даже в производстве уникальное нарушение ограничений происходит только в кажущиеся случайными временами.

Вопросы:

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

2) Каковы наилучшие методы использования генераторов последовательности при использовании hibernate в качестве поставщика JPA?

ответ

3
  1. Да, ваш анализ верен. Вы правильно определили проблему (у нас была аналогичная проблема). И ... если вы собираетесь положить, что в производстве, не забудьте:

    • либо генерировать вручную таблицу последовательности для нового генератора последовательности с правильным начальным значением/начальный ID (в противном случае спящего режима будет начинаться с 1, и вы снова получите)
    • или установите это значение в коде (отметьте initalValue в @SequenceGenerator).
  2. Я не могу перечислить лучшие практики, но, полагаю, вы могли бы снизить предел 50.Также у меня нет опыта работы с PostgreSQL, но в MySQL у вас есть простая таблица для seq. генератор и спящий режим делают весь материал.

0

У меня была аналогичная проблема. В моем случае я импортировал данные напрямую через SQL. Это привело к проблеме с «hibernate_sequence». Hibernate_sequence был по id 123, но в моей таблице были строки, где идентификатор был больше 123.

Смежные вопросы