2011-11-15 17 views
3

非常に多くのオブジェクトをバッチで更新していて、重複を無視したいと思います。 これを行う最善の方法は何ですか?制約違反の例外を伴うHibernateバッチ更新

ConstrainViolationExceptionがスローされると、バッチ内の他のすべてのオブジェクトはすべてNOTになります。

+0

あなたは同様にトランザクションになるだろうことを期待していますか?もしそうなら、あなたは店にいくつかの難しさを持っている... – stevevls

答えて

2

これが私の解決策だった:

private void saveBatch() { 
    StatelessSession session = sessionFactory.openStatelessSession(); 
    Transaction tx = session.beginTransaction(); 

    try { 
     for (Object t : batchList) { 
      session.insert(t); 
     } 
     tx.commit(); 
    } catch (ConstraintViolationException e) { 

     log.info("Duplicate in batch...save individually"); 
     tx.rollback(); 
     session.close(); 
     saveIndividually(); 
     return; 
    } 

    session.close(); 
    batchList.clear(); 
} 

private void saveIndividually() { 
    StatelessSession session = sessionFactory.openStatelessSession(); 
    for (Object t : batchList) { 
     Transaction tx = session.beginTransaction(); 
     session.insert(t); 
     try { 
      tx.commit(); 
     } catch (ConstraintViolationException e) { 
      tx.rollback(); 
      log.warn("Ignoring duplicate: " + t); 
     } 

    } 

    session.close(); 
    batchList.clear(); 
} 
+0

最上位のforループにsession.flush()を追加し、ここに示すように:http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/batch.html。これにより、メモリ不足を防ぐことができ、制約違反を早期に検出できるようになります。 – benvolioT

+0

それは助けになるとは思わない。コミットすると自動的にフラッシュされます。 –

+0

そうですが、バッチリストが非常に大きい場合、メモリが不足することがあります。そのため、ループ内で定期的にフラッシュすることでこれを防ぐことができます。より詳しい説明については、私の最初のコメントのリンクを参照してください。 – benvolioT

0

一貫性を保証する1つの方法は、すべてのエンティティの関連付けに適切なカスケードオプションが設定されていることを確認することです(一定のエンティティを永続化したい場合、その関連に含まれる新しい関連エンティティcascade = "save-update"を設定する必要があります)。

理論的な選択肢は、バッチの操作(各エンティティの挿入など)ごとに個別のトランザクションを作成し、そのトランザクションが例外によってロールバックする場合は、 (失敗したトランザクションのキャッシュを保持して後でそれらを再試行する可能性があります)。しかし、これは実際には実用的ではないでしょう.1つのトランザクション内ですべての操作を実行する場合(真のバッチ更新)よりも処理に時間がかかります。

私がこのようなシナリオに直面したとき、私はJDBCを使ってバッチ操作を行います(Hibernateスキーマを使用し、同じシーケンス生成を確実にすること)。このようにすれば、より速く、そのような問題にもっと正確に対処することはできません。

+0

どのようなカスケードがこれと関係しているかわからない...私のエンティティは、任意の関連がありません。 –

+0

entity1がカスケードオプションなしでentity2に依存する場合、entity2の新しいインスタンスを含むentity1の新しいインスタンスを保存すると、ConstraintViolationが得られます –

関連する問題