2011-11-15 21 views
3

我有一个使用Hibernate的应用程序,我必须包含一个触发器,以便将复制到历史记录表的所有行修改或删除到表中。包括之后的PostgreSQL触发该应用程序无法正常工作,并给这个错误:这个错误出现,因为Hibernate通过SQL的功能受影响行的检查使用PostgreSQL触发器和休眠时发生意外的行计数

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

google搜索,我发现一段时间后更新和返回的行不是预期的行,因为触发器也进行了更新。我已经看到,这可以通过关闭触发器的rowcount来解决。但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(); 

UPDATE:该表是像这样的:

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) 
); 
+0

什么是触发触发器的查询? DooS历史表在{original_key,date}上有唯一的二级索引?顺便说一句:“日期”是一个不好的名字,因为它是一个典型的名字。顺便说一句:也许你应该添加表定义(包括约束)到你的问题。 – wildplasser

+0

@wildplasser确实是这个字段没有被调用的真实表。我在这里改变了它,所以你可以更好地理解它,因为名字不是英文的。如果我直接在表格上进行更新/删除,则触发器完美工作。问题是当我在保存在my_table中的实体上调用EntityManager上的delete()方法时。 – Javi

+0

请显示您的表格定义(相关部分)。 – wildplasser

回答

5

的 “回归NEW”;在DELETE上是可疑的。可能会混淆rowcount(NULL ==零?) http://developer.postgresql.org/pgdocs/postgres/plpgsql-trigger.html(非常通用;不打算侮辱你......)TG_OP上的开关可能是你需要的。

+0

谢谢,这是一个愚蠢的错误。 – Javi

+0

不客气。起初,我对历史感到困惑:now()在事务开始时被冻结,在事务中可以触发多个触发器,在历史文件中创建重复的{timestamp,original_key}对。如果您希望在历史记录中只保留每个事务的一个条目,则需要额外的逻辑。 – wildplasser