【问题标题】:How to return values created by trigger for JOOQ record store?如何返回由触发器为 JOOQ 记录存储创建的值?
【发布时间】:2020-06-04 02:29:18
【问题描述】:

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

对于简单的 CRUD 操作,我们使用 record.store() 并且此记录是 UpdatableRecordImpl,因为基础表包含一个 ID(列 id,PostgreSQL 类型为 serial)此外,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(由触发器生成)的值。但只有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 设置来实现这一点

提前致谢
多米尼克

【问题讨论】:

    标签: postgresql triggers jooq


    【解决方案1】:

    设置withReturnAllOnUpdatableRecord(true) 会在jOOQ 中生成INSERT .. RETURNINGUPDATE .. RETURNING 语句。由于您已经定义了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|
    

    【讨论】:

    • 完美,正如我已经怀疑的那样,错误出现在触发器/函数中......我们尝试越来越多地学习使用它。感谢您快速而正确的回答。
    猜你喜欢
    • 1970-01-01
    • 2018-09-12
    • 2021-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多