如何 return 触发器为 JOOQ 记录存储创建的值?

How to return values created by trigger for JOOQ record store?

几个星期以来,我们使用 JOOQ 作为我们的主要持久性框架,而不是所有那些 Spring 数据 JPA/Hibernate 东西。我真的很感动!!!

对于简单的 CRUD 操作,我们使用 record.store() 并且由于底层 table 包含一个 ID(列 id,PostgreSQL 类型 serial) 此外,JOOQ 配置有 withReturnAllOnUpdatableRecord(true) 并且我们的 table 包含一个触发器来为列 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(由触发器生成)的值。但只有 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));

我假设错误是在触发函数内?触发器应该如何,以实现文档的承诺:

The identity value is not the only value that is generated by default. Specifically, there may be triggers that are used for [...] Users who wish to also automatically fetch these values after all store(), insert(), or update() calls may do so by specifying the returnAllOnUpdatableRecord setting

提前致谢
多米尼克

设置 withReturnAllOnUpdatableRecord(true) 在 jOOQ 中生成 INSERT .. RETURNINGUPDATE .. RETURNING 语句。由于您已经定义了一个 AFTER INSERT 触发器,因此这无助于返回您可能期望的值。在 vanilla 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|