Как вернуть значения, созданные триггером для хранилища записей JOOQ? - PullRequest
1 голос
/ 19 февраля 2020

с тех пор, как несколько недель мы используем JOOQ в качестве основного каркаса персистентности вместо всего этого Spring Data JPA / Hibernate. Я действительно впечатлен !!!

Для простых операций CRUD мы используем record.store(), и эта запись является UpdatableRecordImpl, поскольку в базовой таблице содержится идентификатор (столбец id с PostgreSQL типом *) 1006 *) Кроме того, JOOQ настроен на withReturnAllOnUpdatableRecord(true), и наша таблица содержит триггер для генерации значения для столбца nummer:

CREATE OR REPLACE FUNCTION "public"."after_insert_angebot" () RETURNS trigger
VOLATILE
AS $body$
DECLARE
BEGIN
UPDATE kalkulation_angebot SET nummer = date_part('year', CURRENT_DATE) || '-' || LPAD(NEW.id::text, 3, '0') WHERE id = NEW.id;
RETURN NEW;
END;
$body$ LANGUAGE plpgsql

CREATE TRIGGER "after_insert_angebot"
  AFTER INSERT ON kalkulation_angebot
  FOR EACH ROW
EXECUTE PROCEDURE after_insert_angebot()

Я ожидаю, что после record.store() и из-за withReturnAllOnUpdatableRecord(true) запись содержит значения для идентификатора (сгенерированного типом столбца) и числа (сгенерированного триггером). Но только id заполнен. Я должен вручную установить nummer с помощью дополнительного запроса:

// jooq fetched the new values and the id is available
Integer angebotId = record.getId();

// ... but nummer is missing and has to set manually
angebot.setNummer(jooq.select(KALKULATION_ANGEBOT.NUMMER)
        .from(KALKULATION_ANGEBOT)
        .where(KALKULATION_ANGEBOT.ID.eq(record.getId()))
        .fetchSingleInto(String.class));

Я предполагаю, ошибка в функции триггера? Каким должен быть триггер, чтобы выполнить обещание документации:

Значение идентификатора не является единственным значением, которое генерируется по умолчанию. В частности, могут быть триггеры, которые используются для [...] пользователей, которые также могут автоматически извлекать эти значения после того, как все вызовы store (), insert () или update () могут сделать это, указав параметр returnAllOnUpdatableRecord.

Заранее спасибо
Доминик

1 Ответ

1 голос
/ 20 февраля 2020

Установка withReturnAllOnUpdatableRecord(true) создает оператор INSERT .. RETURNING или UPDATE .. RETURNING в jOOQ. Поскольку вы определили триггер AFTER INSERT, это не поможет вернуть значения, как вы могли ожидать. Попробуйте это в ванили PostgreSQL:

CREATE TABLE kalkulation_angebot (
  id serial,
  nummer text
);

-- Your own TRIGGER below:
CREATE OR REPLACE FUNCTION "public"."after_insert_angebot" () RETURNS trigger
VOLATILE
AS $body$
BEGIN
  UPDATE kalkulation_angebot 
  SET nummer = date_part('year', CURRENT_DATE) || '-' || LPAD(NEW.id::text, 3, '0')
  WHERE id = NEW.id;
  RETURN NEW;
END;
$body$ LANGUAGE plpgsql;

CREATE TRIGGER "after_insert_angebot"
  AFTER INSERT ON kalkulation_angebot
  FOR EACH ROW EXECUTE PROCEDURE after_insert_angebot();

INSERT INTO kalkulation_angebot DEFAULT VALUES RETURNING *;

Вывод:

|id         |nummer  |
|-----------|--------|
|1          |        |

Как насчет того, чтобы заменить триггер на то, что я считаю гораздо более значимым:

CREATE OR REPLACE FUNCTION "public"."before_insert_angebot" () RETURNS trigger
VOLATILE
AS $body$
BEGIN
  NEW.nummer = date_part('year', CURRENT_DATE) || '-' || LPAD(NEW.id::text, 3, '0');
  RETURN NEW;
END;
$body$ LANGUAGE plpgsql;

CREATE TRIGGER "before_insert_angebot"
  BEFORE INSERT ON kalkulation_angebot
  FOR EACH ROW EXECUTE PROCEDURE before_insert_angebot();

INSERT INTO kalkulation_angebot DEFAULT VALUES RETURNING *;

Теперь вывод:

|id         |nummer  |
|-----------|--------|
|1          |2020-001|
...