web-dev-qa-db-ja.com

バッチ処理にStatelessSessionを使用する

から ドキュメント

1000 000行/オブジェクトを挿入する必要がある場合:

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

for ( int i=0; i<100000; i++ ) {
    Customer customer = new Customer(.....);
    session.save(customer);
    if ( i % 20 == 0 ) { //20, same as the JDBC batch size
        //flush a batch of inserts and release memory:
        session.flush();
        session.clear();
    }
}

tx.commit();
session.close();

なぜそのアプローチを使用する必要があるのですか? StatelessSession 1と比較すると、どのようなメリットがありますか。

    StatelessSession session = sessionFactory.openStatelessSession();
    Transaction tx = session.beginTransaction();

    for ( int i=0; i<100000; i++ ) {
      Customer customer = new Customer(.....);
      session.insert(customer);
    }    

    tx.commit();
    session.close();

つまり、この(「代替」)最後の例では、メモリを使用せず、同期する必要がなく、キャッシュをクリーンアップします。これは、このような場合のベストプラクティスになるはずです。なぜ以前のものを使うのですか?

17
ses

リンクしているドキュメントから:

特に、ステートレスセッションは、1次レベルキャッシュを実装せず、2次レベルキャッシュやクエリキャッシュとも対話しません。トランザクション後書きまたは自動ダーティチェックは実装されていません。ステートレスセッションを使用して実行される操作は、関連付けられたインスタンスにカスケードされることはありません。コレクションは、ステートレスセッションでは無視されます。ステートレスセッションを介して実行される操作は、Hibernateのイベントモデルとインターセプターをバイパスします。 1次レベルのキャッシュがないため、ステートレスセッションはデータエイリアシングの影響に対して脆弱です。

これらはいくつかの重要な制限です!

作成しているオブジェクトまたは変更しているのが、個々のオブジェクトのスカラーフィールドに対する単純な変更である場合、ステートレスセッションには、バッチ処理された通常のセッションに比べて不利はないと思います。ただし、もう少し複雑なことをしたい-オブジェクトのコレクション値プロパティ、または最初からカスケードされている別のオブジェクトを操作する-とすると、ステートレスセッションはヘルプよりも邪魔になります。

より一般的には、バッチ処理された通常のセッションが十分なパフォーマンスを提供する場合、ステートレスセッションは単に不必要な複雑さになります。通常のセッションと漠然と似ていますが、APIとセマンティクスが異なります。これは、バグを招くようなものです。

確かにそれが適切なツールである場合もあるかもしれませんが、私はこれらが規則というよりむしろ例外だと思います。

10
Tom Anderson

ステートレスセッションは、Sessionオブジェクトで使用されるセッションへのトランザクションコミットまたはセッションフラッシュメソッドをスキップするため、ステートレスセッションはパフォーマンスの面でSessionよりも優れています。ただし、サービス/ DAOは、親オブジェクトまたは子オブジェクトに対してセッション中のデータ操作を実行してはならないことに注意することが重要です。例外をスローします。また、セッションを明示的に閉じるようにしてください。そうしないと、接続がリークすることになります。

ステートレスセッションでパフォーマンスを向上させるには、Spring駆動トランザクションを使用している場合、Springトランザクションを読み取り専用としてマークし、必要な伝播をNEVERに設定します。

しかし、繰り返しになりますが、オブジェクトモデルを操作する必要がある場合は、これを試さないでください。

@Transactional(value="someTxnManager", readOnly=true, propagation=Propagation.NEVER)
    public List<T> get(...) {

        return daoSupport.get(...);
    }

daoSupport

StatelessSession session = sessionFactory.openStatelessSession();
try{
// do all operations here
}
...
...
finally{
            session.close();
}
1
Anky