Я пытаюсь вставить новую запись с помощью 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 получит правильное значение последовательности.
Решение состоит в том, чтобы удалить все ручные вставки первичных ключей в наши сценарии миграции демонстрационных данных.
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>, вместо этого
resetChangedOnNotNull
до выхода версии 3.5.0. Повторяющиеся ключи по-прежнему остаются проблемой. См. Следующий комментарий.
INSERT
и UPDATE
. Я обновил свой исходный вопрос (см. ОБНОВЛЕНИЕ № 1), указав подробности того, что я испытываю. Либо это ошибка, либо я что-то неправильно сконфигурировал.
RecordListener
или ExecuteListener
... Я только что видел ваше ОБНОВЛЕНИЕ 3, так что это объясняет то же самое. С точки зрения переполнения стека, эти вопросы и ответы начинают немного сбивать с толку обновления в вашем вопросе :-) Обычно рекомендуется задавать только один вопрос за раз, а затем не обновлять вопрос ответами ... Но вы всегда можете ответить на свой вопрос и принять этот ответ сами.
Похожие вопросы
Связанные вопросы
Новые вопросы
java
Java — это высокоуровневый объектно-ориентированный язык программирования. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег часто используется вместе с другими тегами для библиотек и/или фреймворков, используемых разработчиками Java.