質問

パーティション化されたpostgresqlテーブルで休止状態を介してバッチ挿入するための解決策はありますか?現在、このようなエラーが発生しています...

ERROR org.hibernate.jdbc.AbstractBatcher - Exception executing batch:
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
   at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:61)
   at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:46)
   at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:68)....

このリンクを見つけました http://lists.jboss.org/pipermail/hibernate-dev/2007- October/002771.html しかし、この問題が解決されたのか、あるいはそれを回避する方法がウェブ上のどこにも見つかりません

役に立ちましたか?

解決

hibernate.jdbc.factory_class プロパティを設定して、カスタム Batcher を使用してみることもできます。Hibernate がバッチ操作の更新数をチェックしないようにすることで問題が解決する可能性があります。これを実現するには、カスタム Batcher でクラス BatchingBatcher を拡張し、メソッド doExecuteBatch(...) を次のようにオーバーライドします。

    @Override
    protected void doExecuteBatch(PreparedStatement ps) throws SQLException, HibernateException {
        if ( batchSize == 0 ) {
            log.debug( "no batched statements to execute" );
        }
        else {
            if ( log.isDebugEnabled() ) {
                log.debug( "Executing batch size: " + batchSize );
            }

            try {
//              checkRowCounts( ps.executeBatch(), ps );
                ps.executeBatch();
            }
            catch (RuntimeException re) {
                log.error( "Exception executing batch: ", re );
                throw re;
            }
            finally {
                batchSize = 0;
            }

        }

    }

新しいメソッドでは、準備されたステートメントの実行結果はチェックされないことに注意してください。この変更を行うと、予期しない形で休止状態に影響が出る可能性がある (または影響しない可能性がある) ことに注意してください。

他のヒント

ここでは、パーティションテーブルまたは @SQLInsert アノテーションで 2 つのトリガーを使用するように言われています。 http://www.redhat.com/f/pdf/jbw/jmlodgenski_940_scaling_hibernate.pdf 21 ~ 26 ページ (String メソッドを指定する @SQLInsert についても説明しています)。

以下は、マスター内の余分な行を削除する after トリガーを使用した例です。 https://gist.github.com/copiousfreetime/59067

挿入のトリガーの代わりに RULES を使用できる場合に表示されます。その場合、正しい数値を返すことができますが、WHERE ステートメントのない単一の RULE を使用した場合に限ります。

参照1

参照2

参照3

別のオプションとして、パーティション テーブルを「ラップ」するビューを作成し、マスター テーブルに余分な不要な行を誤って追加することなく、行の更新が成功したことを示す新しい行を返すこともできます。

create view tablename_view as select * from tablename; -- create trivial wrapping view

CREATE OR REPLACE FUNCTION partitioned_insert_trigger() -- partitioned insert trigger
RETURNS TRIGGER AS $$
BEGIN
   IF (NEW.partition_key>= 5500000000 AND
       NEW.partition_key <  6000000000) THEN
      INSERT INTO tablename_55_59 VALUES (NEW.*);
   ELSIF (NEW.partition_key >= 5000000000 AND
          NEW.partition_key <  5500000000) THEN
      INSERT INTO tablename_50_54 VALUES (NEW.*);
   ELSIF (NEW.partition_key >= 500000000 AND
          NEW.partition_key  <  1000000000) THEN
      INSERT INTO tablename_5_9 VALUES (NEW.*);
   ELSIF (NEW.partition_key >= 0 AND
          NEW.partition_key <  500000000) THEN
      INSERT INTO tablename_0_4 VALUES (NEW.*);
   ELSE
      RAISE EXCEPTION 'partition key is out of range.  Fix the trigger function';
   END IF;
   RETURN NEW; -- RETURN NEW in this case, typically you'd return NULL from this trigger, but for views we return NEW
END;
$$
LANGUAGE plpgsql;

CREATE TRIGGER insert_view_trigger
   INSTEAD OF INSERT ON tablename_view
   FOR EACH ROW EXECUTE PROCEDURE partitioned_insert_trigger(); -- create "INSTEAD OF" trigger

参照: http://www.postgresql.org/docs/9.2/static/trigger-setting.html

ビュー ラッパー ルートを選択した場合は、削除と更新に対して簡単な「代わりに」トリガーを定義することもオプションの 1 つです。そうすれば、すべてのトランザクションで通常のテーブルの代わりにビュー テーブルの名前を使用するだけで済みます。

ビューを使用するもう 1 つのオプションは、メイン テーブルへの挿入が [そのトリガーを使用する] ビューに送られるように挿入ルールを作成することです (例: すでに partitioned_insert_trigger 上記のように作成された tablename_view と insert_view_trigger)

create RULE use_right_inserter_tablename AS
      ON INSERT TO tablename
      DO INSTEAD insert into tablename_view VALUES (NEW.*);

次に、新しい作業ビュー ラッパー挿入を使用します。

thnx!それはうまくいきました、今のところ問題は発生していません:)....1つだけ...実装しなければならなかった BatcherFactory クラスに入れて、 persistence.xml このようにファイル:

property name="hibernate.jdbc.factory_class" value="path.to.my.batcher.factory.implementation"

そのファクトリーから、上記のコードでバッチャー実装を呼び出しました

PS Hibernate Core 3.2.6 Ga

もう一度ありがとう

多くの検索で更新された行が返されることを期待していることが判明した後、休止状態を通じてドキュメントを挿入しているときに同じ問題に直面しました。そのため、トリガープロシージャでnullの代わりにnewに変更すると、以下に示すように問題が解決されます。

新しいものを返す

同じ問題に対する別の解決策を見つけました このウェブページで:

これは、@rogerdpackが言ったのと同じ解決策を示唆しており、 Null を返す戻る NEW, そして、クエリを使用してマスター内の重複したタプルを削除する新しいトリガーを追加します。

DELETE FROM ONLY master_table;
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top