2013-08-13 5 views
12

私は、各スレッドがオブジェクトを取得し、それをテーブルに挿入しようとするマルチスレッドアプリケーションにHibernateを使用しようとしています。私のコードは以下のようになります。 スレッドごとにローカルなハイバネートセッションオブジェクトを持ち、各InsertDataにbeginTransactionとcommitを行います。マルチスレッドアプリケーションでHibernateを使用するには?

私が直面しています問題は何度も私が得ることである「org.hibernate.TransactionException:ネストされたトランザクションがサポートされていない」

私は私がやっていることは正しいかどうかはわからない休止状態に新しいですので、またはない?私はマルチスレッドアプリケーションでhibernateを使用する正しい方法と上記の例外を回避する方法を教えてください。

おかげ

public class Worker extends Thread { 
private Session session = null; 

Worker() { 
    SessionFactory sf = HibernateUtil.getSessionFactory(); // Singleton 
    session = sf.openSession(); 
    session.setFlushMode(FlushMode.ALWAYS); 
} 

public void run() { 
    // Some loop which will run thousand of times 
    for (....) 
    { 
     InsertData(b); 
    } 
    session.close(); 
} 

// BlogPost Table has (pk = id AutoGenerated), dateTime, blogdescription etc. 
private void InsertData(BlogPost b) { 
    session.beginTransaction(); 
    Long id = (Long) session.save(b); 
    b.setId(id); 
    session.getTransaction().commit(); 
} 
} 

私の休止状態の設定ファイルがc3p0.min_size=10c3p0.max_size=20限り、あなたが複数のスレッド間でセッションオブジェクトを共有していないように、セッション・オブジェクト・スレッド単位で

+0

これは 'b.setId()'であるはずですか? –

+0

うん、ちょうどそれを修正しました。 Typoは私の実際のコードの最小限の例を作成しようとしている間に起こった。 – Rahul

答えて

10

、あなたは罰金になりました。

エラーは、マルチスレッドの使用やセッション管理とは関係ありません。 session.save()の使用とIDの明示的な設定は正しくはありません。

BlogPostのマッピングがわかりませんが、idフィールドをプライマリキーとして使用するようにHibernateに指示していて、プライマリキーにネイティブジェネレータを使用している場合は、これが必要です:

session.beginTransaction(); 
session.persist(b); 
session.flush(); // only needed if flush mode is "manual" 
session.getTransaction().commit(); 

Hibernateは(save()が取引を気にしません)persist()は、インサートは、トランザクションの範囲内で発生するようになります、あなたのためのIDを記入します。フラッシュモードが手動に設定されていない場合は、flush()に電話する必要はありません。Transaction.commit()がそれを処理します。

persist()を使用すると、BlogPostのIDはセッションがフラッシュされるまで設定されないことに注意してください。これはここでの使用に適しています。

は優雅にエラーを処理するには、次の

try { 
    session.beginTransaction(); 
    try { 
     session.persist(b); 
     session.flush(); // only needed if flush mode is "manual" 
     session.getTransaction().commit(); 
    } catch (Exception x) { 
     session.getTransaction().rollback(); 
     // log the error 
    } 
} catch (Exception x) { 
    // log the error 
} 

をちなみに、私はBlogPost.setId()プライベート、またはパッケージを可視化を示唆しています。他のクラスが明示的にIDを設定している場合は、実装エラーです(元のジェネレータとidを主キーと見なします)。

+1

ありがとうございましたJason、私はロールバックを持っていませんでした。これにより、以前の例外がスレッドに対してトランザクションを開いたままにし、その後のbeginTransationが "TransactionException"をスローするのに使用されました。 – Rahul

関連する問題