Генератор последовательности OpenJPA с отрицательными значениями

#java #db2 #openjpa #db2-zos

#java #db2 #openjpa #db2-zos

Вопрос:

Среда: Websphere 8.5, OpenJPA 2.0, DB2 z /OS

Есть две таблицы: одна с проверенными данными, а другая с черновыми данными (промежуточная таблица) Представление, в которых отображается информация из обеих таблиц.
Чтобы избежать столкновения первичных ключей, я решил, что промежуточная таблица будет иметь отрицательные значения в качестве первичного ключа. Он работал в обычном SQL, но мой подход потерпел неудачу, когда я попытался определить генератор для промежуточной таблицы в коде Java

Генератор для отрицательного ключа был определен следующим образом:

 CREATE SEQUENCE X AS INTEGER START WITH -1 INCREMENT BY -1
MINVALUE -999999 MAXVALUE 0
 

На стороне объекта:

 @Id
@SequenceGenerator(name="X", sequenceName="X")
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="X")
@Column(name = "ID")`
 

Первый элемент был создан успешно (со значением -1), но вставка второго элемента не удалась с

ДИАПАЗОН ЗНАЧЕНИЙ ДЛЯ СТОЛБЦА ИДЕНТИФИКАТОРА ИЛИ ПОСЛЕДОВАТЕЛЬНОСТИ ИСЧЕРПАН. SQLCODE=-359, SQLSTATE=23522

Можете ли вы помочь мне определить @SequenceGenerator ? Возможно ли это в Open JPA 2.0? Возможно, определение последовательности было неправильным (МИНИМАЛЬНОЕ ЗНАЧЕНИЕ / МАКСИМАЛЬНОЕ значение)

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

1. В качестве краткосрочного исправления я изменил генератор: «НАЧНИТЕ С -99999 С ШАГОМ 1». Не очень красиво, но это работает.

2. Должно быть, это ошибка / особенность, специфичная для DB2 z / OS — она работает, как и ожидалось, в Linux.

Ответ №1:

Во-первых, я думаю, что ваш вариант сделать «НАЧАТЬ С -99999 С ШАГОМ 1» — лучший вариант. Я не совсем понимаю, почему вы считаете, что это «некрасиво». Если вы сделаете это:

СОЗДАЙТЕ ПОСЛЕДОВАТЕЛЬНОСТЬ SEQ_MYSEQ КАК ЦЕЛОЕ ЧИСЛО, НАЧИНАЯ С -99999 И УВЕЛИЧИВАЯ НА 1 МИНИМАЛЬНОЕ ЗНАЧЕНИЕ -999999 МАКСИМАЛЬНОЕ ЗНАЧЕНИЕ 0

Вы все еще находитесь в диапазоне от -99999 до 0, верно?

Как я объясню ниже, я думаю, что OpenJPA и EclipseLink любят подсчитывать. Так что я думаю, вам с этим повезет больше.

Тем не менее, позвольте мне ответить на ваш вступительный вопрос. Я провел тест на OpenJPA и EclipseLink (поскольку WebSphere использует Eclipselink в WAS v9 и Liberty). Я не могу заставить ваш сценарий работать с EclipseLink, но мог заставить его работать с OpenJPA (но это было некрасиво). Позвольте мне указать, что я сделал: это SQL, с помощью которого я определил свою последовательность (так же, как вы указали в описании):

СОЗДАЙТЕ ПОСЛЕДОВАТЕЛЬНОСТЬ SEQ_MYSEQ КАК ЦЕЛОЕ ЧИСЛО, НАЧИНАЯ С -1 С ШАГОМ -1 МИНИМАЛЬНОЕ ЗНАЧЕНИЕ -999999 МАКСИМАЛЬНОЕ ЗНАЧЕНИЕ 0;

Я определил свой генератор последовательностей в своей сущности как:

@Id @SequenceGenerator(name = «IDGENERATOR», sequenceName = «SEQ_MYSEQ», allocationSize = 1, initialValue = -1) @GeneratedValue(стратегия = GenerationType.ПОСЛЕДОВАТЕЛЬНОСТЬ, генератор = «IDGENERATOR») private int id;

Обратите внимание, что я говорю JPA начинать с -1 и использовать allocationSize, равный 1. В JavaDocs указано значение по умолчанию 50. Один облом (но не ограничитель показа) с размером распределения 1 заключается в том, что поставщик JPA будет обращаться к базе данных для каждого значения последовательности (т. Е. локальное кэширование не будет использоваться). Однако, если это не используется, кажется, что и OpenJPA, и EclipseLink хотят подсчитать размер распределения. Это жестко запрограммировано для подсчета. То есть либо один из них запросит у базы данных следующее значение, а затем подсчитает оттуда по allocationSize, А НЕ обратный отсчет. В OpenJPA вам необходимо использовать это свойство:

В противном случае по умолчанию OpenJPA выполняет «ALTER SEQUENCE», чтобы убедиться, что ПРИРАЩЕНИЕ BY, определенное в SequenceGenerator, соответствует тому, что есть в базе данных. Если я не добавлю это свойство, я получу такое же исключение об исчерпании диапазона. В любом случае, с этим все хорошо работает на OpenJPA. На EclipseLink я получаю это исключение:

Описание исключения: Последовательность с именем [SEQ_MYSEQ] настроена неправильно. Его приращение не соответствует размеру предварительного выделения. в org.eclipse.persistence.internal.jpa.EntityManagerImpl.persist(EntityManagerImpl.java:510) в hat.test.MySeqTest.main(MySeqTest.java:28)

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

Спасибо,

Хит Томанн