使用 PostgreSQL 触发器和 hibernate 时出现意外的行计数

发布于 2024-12-15 18:04:57 字数 1975 浏览 3 评论 0原文

我有一个使用 Hibernate 的应用程序,我必须包含一个触发器来将表中修改或删除的所有行复制到历史表。添加 PostgreSQL 触发器后,应用程序无法正常工作并给出以下错误:

org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: 批量更新从更新[0]返回意外的行数;实际行 计数:0;预期:1;嵌套异常是 org.hibernate.StaleStateException:批量更新意外返回 更新的行数[0];实际行数:0;预期:1

经过谷歌搜索一段时间后,我发现出现此错误是因为 Hibernate 通过 sql 更新检查了受影响的行,并且返回的行不是预期的行,因为触发器还执行了更新。我发现可以通过关闭触发器上的行计数来解决此问题。但 PostgreSQL 似乎没有“set nocount on”的替代方案。

如何解决 PostgreSQL 触发器中的问题,如下所示?

谢谢

CREATE OR REPLACE FUNCTION my_trigger_fnc() RETURNS TRIGGER AS $my_trigger_fnc$
    DECLARE
        nowDate timestamp := now();
    BEGIN

        INSERT INTO historial_table (
                id,
                date_now,
                id_mytable,
                --some other fields
                ...
                ) 
        VALUES (              
                nextVal('historial_table_seq'),
                nowDate,
                OLD.id_mytable
                --some other fields
                ...
               );
        RETURN NEW;
    END;
$my_trigger_fnc$ LANGUAGE plpgsql;

CREATE TRIGGER my_trigger BEFORE UPDATE OR DELETE 
    ON my_table FOR EACH ROW 
    EXECUTE PROCEDURE my_trigger_fnc();

更新:表格如下:

CREATE TABLE historial_table(
    id integer,
    date_now timestamp NOT NULL,
    id_mytable integer NOT NULL,
    nserie character varying(255),
    idstore integer,
    idmodel integer,
    automatic boolean,
    broken boolean,
    idAlb integer,
    idInc integer,
    id_item integer,
    date_assign timestamp,
    PRIMARY KEY (id)  
);

CREATE TABLE my_table(
    id_mytable integer NOT NULL,
    nserie character varying(255),
    idstore integer,
    idmodel integer,
    automatic boolean,
    broken boolean,
    idAlb integer,
    idInc integer,
    id_item integer,
    date_assign timestamp,
    PRIMARY KEY (id_mytable)  
);

I have an application which uses Hibernate and I have to include a trigger to copy to a history table all rows modified or deleted in a table. After including the PostgreSQL trigger the application doesn't work properly and is giving this error:

org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException:
Batch update returned unexpected row count from update [0]; actual row
count: 0; expected: 1; nested exception is
org.hibernate.StaleStateException: Batch update returned unexpected
row count from update [0]; actual row count: 0; expected: 1

After googling for a while I've discovered that this error comes because Hibernate does a checking of the affected rows by the sql update and the returned rows aren't the expected ones because the trigger has also done an update. I've seen that this could be fixed by turning off rowcount on the trigger. But PostgreSQL doesn't seem to have an alternative for 'set nocount on'.

How can I solve the problem in a trigger of PostgreSQL like the shown below?

Thanks

CREATE OR REPLACE FUNCTION my_trigger_fnc() RETURNS TRIGGER AS $my_trigger_fnc$
    DECLARE
        nowDate timestamp := now();
    BEGIN

        INSERT INTO historial_table (
                id,
                date_now,
                id_mytable,
                --some other fields
                ...
                ) 
        VALUES (              
                nextVal('historial_table_seq'),
                nowDate,
                OLD.id_mytable
                --some other fields
                ...
               );
        RETURN NEW;
    END;
$my_trigger_fnc$ LANGUAGE plpgsql;

CREATE TRIGGER my_trigger BEFORE UPDATE OR DELETE 
    ON my_table FOR EACH ROW 
    EXECUTE PROCEDURE my_trigger_fnc();

UPDATE: the tables are like this one:

CREATE TABLE historial_table(
    id integer,
    date_now timestamp NOT NULL,
    id_mytable integer NOT NULL,
    nserie character varying(255),
    idstore integer,
    idmodel integer,
    automatic boolean,
    broken boolean,
    idAlb integer,
    idInc integer,
    id_item integer,
    date_assign timestamp,
    PRIMARY KEY (id)  
);

CREATE TABLE my_table(
    id_mytable integer NOT NULL,
    nserie character varying(255),
    idstore integer,
    idmodel integer,
    automatic boolean,
    broken boolean,
    idAlb integer,
    idInc integer,
    id_item integer,
    date_assign timestamp,
    PRIMARY KEY (id_mytable)  
);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

别把无礼当个性 2024-12-22 18:04:57

“返回新;”对 DELETE 有疑问。可能会混淆行计数(NULL==0?)
http://developer.postgresql.org/pgdocs/postgres/plpgsql-trigger.html (非常通用;无意侮辱您...) TG_OP 上的开关可能正是您所需要的。

The "return NEW;" is suspicious on DELETE. Might confuse the rowcount (NULL==zero?)
http://developer.postgresql.org/pgdocs/postgres/plpgsql-trigger.html (very generic; not intended to insult you ...) The switch on TG_OP is probably what you need.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文