Реализуйте функцию batchMerge() в JOOQ

#java #sql #postgresql #jooq

Вопрос:

Мне нужно «вставить» список предметов.

 class Item {
 private UUID id;
 private UUID anotherId;
 private List<String> things;
 ...
}
 

Если элемент id и anotherId уже существует, другие значения должны быть заменены новым элементом. Если это не так, элемент должен быть вставлен как новая запись.

Я наткнулся на batchMerge JOOQ и подумал, что это похоже на «upsert». К сожалению, в Интернете мало документации, так как это довольно новый метод JOOQ на момент написания.

Я пытался

 List<ItemRecord> items = ... //built from context.newRecord(ITEM) then added to a list
context.batchMerge(items).execute();
 

думая, что он автоматически получит обновленные поля. Значения не обновляются, если строка уже существует. Он вставляет новую запись, если она еще не существует.

Я наткнулся на эту документацию merge , но не знаю, как ее перевести batchMerge . https://www.jooq.org/doc/3.1/manual/sql-building/sql-statements/merge-statement/

Я довольно новичок в SQL и JOOQ. Я использую PostgreSQL в качестве базы данных.

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

1. Я вижу тег <sql>, но действительно ли это связано с языком SQL <sql>?

2. Вы найдете все, что хотите знать, в документе API: jooq.org/javadoc/latest/org.jooq/org/jooq/…

3. Вставить… По дубликату ключа может помочь?

Ответ №1:

В настоящее время (по состоянию на 3.15 jOOQ) пакетные выполнения в jOOQ не могут извлекать сгенерированные идентификаторы, см.: https://github.com/jOOQ/jOOQ/issues/3327

Однако, поскольку вы используете UUID типы для своих идентификаторов (в отличие от сгенерированных последовательностями), вам вообще нужен сервер для генерации идентификаторов? С таким же успехом вы можете сгенерировать их уже в клиенте и вставить вместе с остальными.

Ответ №2:

JOOQ batchMerge() работает, как и ожидалось, с Postgres.

На самом деле проблема была не в ДЖУКЕ. Служба, которая вызывает метод репо для batchMerge, помечена @Transactional . Это весенняя аннотация, которая имеет функцию отката. Вот почему кажется, что он не сохраняется в базе данных. Я отметил это как @Transactional(noRollbackFor = CustomException.class) решение моей проблемы.