2011-11-15 2 views
3

私はHibernateを使用するアプリケーションを持っており、履歴テーブルに変更または削除された行をテーブルにコピーする必要があります。 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

:含めた後、PostgreSQLは、アプリケーションが正常に動作しないと、このエラーを与えているトリガー更新が行われたため、返された行は予想された行ではありません。私はこれがトリガーの行数をオフにすることで修正できることを見てきました。しかし、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:テーブルはこの1つのようなものです:

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

トリガを発生させたクエリは何ですか?履歴テーブルに{original_key、date}のユニークなセカンダリインデックスがありますか? BTW: "日付"は、通常の名前なので、列の悪い名前です。ところで、おそらくあなたの質問にテーブル定義(制約を含む)を追加する必要があります。 – wildplasser

+0

@wildplasser実際には、フィールドがこのように呼び出されていない実際のテーブルです。私は名前が英語でないので、あなたはそれをよりよく理解できるように、ここでそれを変更しました。テーブル上で直接更新/削除を行うと、トリガーは完全に機能します。問題は、my_tableに保存されたエンティティでEntityManagerのdelete()メソッドを呼び出すときです。 – Javi

+0

あなたのテーブル定義(の関連部分)を表示してください。 – wildplasser

答えて

5

"NEWを返します。" DELETEで疑わしい。行カウント(NULL ==ゼロ?)を混乱させるかもしれません http://developer.postgresql.org/pgdocs/postgres/plpgsql-trigger.html(非常に一般的で、あなたを侮辱するつもりはありません...)TG_OPのスイッチは、おそらく必要なものです。

+0

ありがとう、それは愚かなエラーでした。 – Javi

+0

あなたは大歓迎です。最初は私は履歴で混乱しました。now()はトランザクション開始時に固定され、トランザクション内で複数のトリガーが起動され、履歴ファイルに重複した{timestamp、original_key}のペアが作成されます。履歴にトランザクションごとに1つのエントリしか保存しない場合は、追加のロジックが必要です。 – wildplasser

関連する問題