7

私のプロジェクトは春のトランザクションマネージャーで休止状態を使用しており、私のデータベースはpostgresです(無関係かもしれません)。

私は大きなxmlファイルを読み込んで、それらからオブジェクトを構築しようとしています(オブジェクトは大きくありませんが、量は大きいです)。それらをデータベースに挿入します。

万が一オブジェクトの 1 つがデータベースの制約に違反すると、プロセス全体が停止します。データベースの制約に違反するものをスキップするにはどうすればよいですか? または、IDなどをログファイルに記録しますか?

質問の更新:

私はSOをブラウズしてきましたが、バッチ挿入にはステートレスセッションを使用することをお勧めしますが、それでも同じ問題が発生し、挿入が停止することがわかりました:

May 26, 2012 4:45:47 PM org.hibernate.util.JDBCExceptionReporter logExceptions
SEVERE: ERROR: duplicate key value violates unique constraint "UN_FK"
  Detail: Key (fid)=(H1) already exists.

簡単にするために、xml を解析して db に挿入するためのコードの関連部分を次に示します。

//class field
@Autowired
private SessionFactory sessionFactory;

@Override
public void startDocument() throws SAXException {
    session = sessionFactory.getCurrentSession();
}

@Override
public void endElement(String uri, String localName, String qName) throws SAXException  {
if (qName.equalsIgnoreCase("FILM")) {
        movie.setCategory(category);
        movie.setAdded(new Date());
        session.insert(movie);
    }
}

私は app-ctx でこのプロパティhibernate.jdbc.batch_sizeを 100 に設定しています。これを避けるために、挿入前に選択する必要がありますか?

更新 2:

セッションの代わりに使用するStatelessSessionと、約20回の挿入が発生し、例外や何もなく処理が無期限に停止します。

20という数字は、Tomcatとの接続をプールしているためだと思いますmaxActive="20".

バウンティの更新:

誰かが解決策を提供してくれるのを本当に楽しみにしています(可能であれば防御的な選択なしで)。statelessSession または単にセッションを使用します。

4

6 に答える 6

4

列が null 可能であるか、最大幅があるかなど、ほとんどのタイプの制約は、Hibernate Validatorを使用して確認できます。永続化を試みる前に、オブジェクトの検証を手動で実行するだけです。

いくつかのもの、特に一意の制約については、「防御的な」選択を実行して衝突が存在するかどうかを確認するか、既に挿入されているメモリ内の値のセットを維持する必要があります。

于 2012-05-25T23:47:46.637 に答える
2

xmlファイルから大量のオブジェクトを挿入するには、SpringBatchの使用を検討する必要があります。パラメータskip-limitを使用すると、バッチプロセスを停止する前に、xmlに含まれる可能性のある誤った行の数を知ることができます。skip-policyとskippable-exceptionも確認してください。Springのドキュメントの「ステップの構成」を参照してください。

Spring Batchを使用したくない場合は、プロセスを最後まで続行できる単純なtrycatchを使用してください。

于 2012-05-25T23:54:54.350 に答える
2

これがすべて 1 つの大きな取引にならなければならないのはなぜだと思いますか? あなたが実際に説明したことはすべて、あなたが実際にここで多くの取引を行っていることを意味します。「エラーが発生した」オブジェクトの場合は、そのエンティティを削除してトランザクションをロールバックします。「FILM」要素がオブジェクトのグラフを定義する場合、もう少し複雑になりますが、考え方は同じです。

于 2012-06-01T02:53:12.757 に答える
1

Affeは、挿入前にディフェンシブ セレクトを行うという正しいアプローチを取っていると思います。

各挿入の前にセーブポイントを使用し、例外がスローされた場合はセーブポイントにロールバックすることを検討できます。セーブポイントを作成すると、パフォーマンスのオーバーヘッドが発生します。完了したら、セーブポイントを解放する必要があります。

AbstractTransactionStatus.setSavepoint()を参照するか、JDBC 接続プールsetSavepoint rollback(Savepoint)およびreleaseSavepoint( Savepoint) にアクセスできる場合

于 2012-06-01T00:14:02.283 に答える