2008-09-17 13 views
10

パーティション化されたpostgresqlテーブルにhibernate経由でバッチインサートするためのソリューションはありますか?現在、私はこの問題は解決し、私はこのリンクhttp://lists.jboss.org/pipermail/hibernate-dev/2007-October/002771.htmlを発見したが、私はウェブ上のどこ見つけることができない。このようなエラー...パーティション化されたpostgresqlでhibernateを挿入するバッチ

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).... 

をされて取得していますか、それは周りの

+0

その他のHibernate 3.5のソリューションはありますか? –

答えて

4

を得ることができる方法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; 
      } 

     } 

    } 

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

2

thnx!

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

:私はこのような 、BatcherFactoryクラスを実装し、それがpersistence.xmlファイルをint型入れていた)......あなた一つのこと... :それはトリック、これまでのところまでpoped何の問題も、やりましたその工場から、私は3.2.6 GA

PS 休止コア上記のコードで自分のバッチャー実装

おかげで彼らが言うに再び

+0

バッチカウントを無視すると、問題が解決するのですか、それとも単にエラーを無視しますか? 同じエラーが発生していますが、なぜそれが起こっているのか、またはスキップするためにBatcherをオーバーライドしようとすると何を意味するのかわかりません。 – Dougnukem

+1

これはHibernate 3.2.6 GAでどのように動作しますか?BatchingBatcher実装はprivateフィールドとしてbatchSizeを持っていますので、拡張してアクセスできません。 – Dougnukem

+1

それは問題を無視しますが、すべての値はDBに入っていますので、私のためのトリックです...私はAbstractBatcherクラスを拡張しました – tropikalista

2

と呼ばれてきましたパーティション化されたテーブル内の2つのトリガまたは@SQLInsertアノテーションをここで使用してください:http://www.redhat.com/f/pdf/jbw/jmlodgenski_940_scaling_hibernate.pdf 21-26ページ(@SQLInsertにはStringメソッドを指定しています)。ここで

はマスターに余分な行を削除するには、トリガーの後での例です:https://gist.github.com/copiousfreetime/59067

+0

@SQLInsertメソッドが機能しました。 –

1

は、あなたの代わりに、インサートのトリガーのルールを使用できるかどうか、それは右の数を返すことができます表示されますが、だけでWHERE文のない単一のルール。

ref1

ref2

ref3

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

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 

REF:http://www.postgresql.org/docs/9.2/static/trigger-definition.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.*); 

次に、新しいワーキングビューラッパー挿入を使用します。

0

休止を通じて文書を挿入しながら、検索の多くは、更新された行ではなく

以下のように問題を解決しますトリガプロシージャの新しいにヌル変更それのように返されるべきであることを期待していることが判明した後、私は同じ問題に直面しました

RETURN NEW