Я пытаюсь вставить новую запись с помощью UpdatableRecords в jOOQ 3.4.2. Шаблон чрезвычайно лаконичен и приятен в использовании, за исключением того, что INSERT считывает нулевые значения как нулевые и игнорирует значения по умолчанию или сгенерированный индекс. Как я могу использовать UpdatableRecord для вставки, которая учитывает значения по умолчанию и сгенерированные индексы?

Вот моя таблица:

CREATE TABLE aragorn_sys.org_person (
    org_person_id SERIAL  NOT NULL,
    first_name CHARACTER VARYING(128)  NOT NULL,
    last_name CHARACTER VARYING(128)  NOT NULL,
    created_time TIMESTAMP WITH TIME ZONE DEFAULT current_timestamp  NOT NULL,
    created_by_user_id INTEGER,
    last_modified_time TIMESTAMP WITH TIME ZONE,
    last_modified_by_user_id INTEGER,
    org_id INTEGER  NOT NULL,
    CONSTRAINT PK_org_person PRIMARY KEY (org_person_id)
);

Обратите внимание на мой первичный ключ и значения по умолчанию. Вот мой код jOOQ:

// orgPerson represents a POJO filled with my values to be inserted and null for everything else
// Note that orgPerson.orgPersonId is null
OrgPersonRecord orgPersonRecord = create.newRecord( ORG_PERSON, orgPerson );
Integer orgPersonId = create.executeInsert( orgPersonRecord );

Но когда я запускаю это, я получаю ошибку null value in column "org_person_id" violates not-null constraint.

Я заметил, что в документации jOOQ говорится, что вызов newRecord автоматически устанавливает для всех внутренних флагов «изменено» значение true в UpdatableRecord. Итак, я попробовал это:

// orgPerson represents a POJO filled with my values to be inserted and null for everything else
// Note that orgPerson.orgPersonId is null
OrgPersonRecord orgPersonRecord = create.newRecord( ORG_PERSON, orgPerson );
orgPersonRecord.changed( ORG_PERSON.ORG_PERSON_ID, false );
orgPersonRecord.changed( ORG_PERSON.CREATED_TIME, false );
orgPersonRecord.insert()
Integer orgPersonId = orgPersonRecord.getOrgPersonId();

Но это дает мне ошибку ERROR: duplicate key value violates unique constraint "pk_org_person". И когда я делаю это неоднократно, значения, кажется, продолжают увеличиваться на 1. На самом деле это не имеет смысла для меня, но мой больший вопрос: Есть ли хороший способ сделать INSERT на основе значений моих объектов или, что еще лучше, просто включить только ненулевые столбцы ?

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

Кстати, работать с jOOQ пока просто фантастика. Лукас, спасибо за этот замечательный инструмент!

ОБНОВЛЕНИЕ №1:

«Непустая проблема» решается в ответе Лукаса ниже, и это легко исправить.

Что касается повторяющихся первичных ключей, я определенно не путаю INSERT с UPDATE. Когда я запускаю приведенный выше код (небольшое обновление после исходного сообщения), jOOQ, кажется, произвольно выбирает «начальное» значение первичного ключа для OrgPersonId. Например, когда я впервые загружаю свою среду, jOOQ может начинаться с «11» для OrgPersonId.

Затем, когда я выполняю INSERT, jOOQ попытается предоставить значение "11" для OrgPersonId, я получу ERROR: duplicate key value, и INSERT завершится ошибкой. Если я затем повторю INSERT, jOOQ будет использовать «12», а затем «13». Успешно или нет, в зависимости от того, доступен ли этот идентификатор, но он не «начинается» с правильного идентификатора.

Руководство (http: // www.jooq.org/doc/3.4/manual/sql-execution/crud-with-updatablerecords/identity-values/) говорит, что If you're using jOOQ's code generator, the above table will generate a org.jooq.UpdatableRecord with an IDENTITY column. This information is used by jOOQ internally, to update IDs after calling store().

ОБНОВЛЕНИЕ №2:

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

ОБНОВЛЕНИЕ № 3:

Проблема решена. Мы используем FlywayDB (еще один замечательный инструмент) для автоматизации миграции схемы нашей базы данных, и у нас было несколько операторов INSERT в наших сценариях Flyway, которые вручную ВСТАВЛЯЛИ номер идентификатора. Это было удобно, потому что мы хотели создать кучу фиктивных данных и гарантировать правильные отношения внешних ключей.

Но ручное указание приращения первичного ключа не продвигает последовательность Postgres! Следовательно, нам пришлось пройти через последовательность Postgres, прежде чем (правильно работающий) jOOQ получит правильное значение последовательности.

Решение состоит в том, чтобы удалить все ручные вставки первичных ключей в наши сценарии миграции демонстрационных данных.

3
Josh Padnick 20 Авг 2014 в 11:35
«Лукас, спасибо за этот замечательный инструмент!» : Пожалуйста ;-) Просто чтобы быть уверенным - недавно в этой области были исправлены некоторые проблемы. Не могли бы вы указать, какую версию jOOQ вы используете?
 – 
Lukas Eder
20 Авг 2014 в 13:09
Конечно, использую jOOQ 3.4.2
 – 
Josh Padnick
20 Авг 2014 в 17:44
Хорошо, я займусь этим завтра
 – 
Lukas Eder
21 Авг 2014 в 10:05
Спасибо! Кстати, только что смотрел вашу презентацию GeeCon; очень хорошее освещение эволюции Java + SQL.
 – 
Josh Padnick
21 Авг 2014 в 18:04

1 ответ

Лучший ответ

Нарушает ненулевое ограничение

Первая часть, которую вы описываете, - это недостаток (# 3582), который связана с предыдущей проблемой (# 2700), которая принудительно сохраняла null значения, загруженные из POJO в jOOQ Records для столбцов базы данных, которые являются NOT NULL. Исправление будет в jOOQ 3.5.0, 3.4.3, 3.3.4 и 3.2.7.

Повторяющееся значение ключа нарушает уникальное ограничение "pk_org_person"

Вторая часть, вероятно, вызвана тем, что вы действительно загружаете существующую запись, а затем вызываете executeInsert() на нем (обратите внимание на INSERT, который всегда будет выполнять оператор INSERT). Вы можете позвонить executeUpdate() < / a>, вместо этого

2
imTachu 3 Янв 2019 в 12:57
Спасибо, Лукас. Что касается «ограничения ненулевого значения», вы совершенно правы. Это легко исправить, установив флаги вручную или скопировав свой метод resetChangedOnNotNull до выхода версии 3.5.0. Повторяющиеся ключи по-прежнему остаются проблемой. См. Следующий комментарий.
 – 
Josh Padnick
22 Авг 2014 в 22:46
Что касается повторяющихся ключей, это определенно не связано со случайным совпадением INSERT и UPDATE. Я обновил свой исходный вопрос (см. ОБНОВЛЕНИЕ № 1), указав подробности того, что я испытываю. Либо это ошибка, либо я что-то неправильно сконфигурировал.
 – 
Josh Padnick
22 Авг 2014 в 22:48
Джош, jOOQ не «выбирает значения идентификаторов» за вас. Только база данных генерирует идентификаторы, или вы можете сделать это самостоятельно, используя RecordListener или ExecuteListener ... Я только что видел ваше ОБНОВЛЕНИЕ 3, так что это объясняет то же самое. С точки зрения переполнения стека, эти вопросы и ответы начинают немного сбивать с толку обновления в вашем вопросе :-) Обычно рекомендуется задавать только один вопрос за раз, а затем не обновлять вопрос ответами ... Но вы всегда можете ответить на свой вопрос и принять этот ответ сами.
 – 
Lukas Eder
25 Авг 2014 в 10:54
Спасибо, Лукас. Я согласен, что этот пост запутался; Я буду лучше организовывать это в будущем. :)
 – 
Josh Padnick
25 Авг 2014 в 22:25