2017-10-31 16 views
0

これは一般的な問題だと思いますが、検索の結果、関連するものは見つけられませんでした。Dropwizard @UnitOfWork非同期データベースコール

私が抱えている問題は、@UnitOfWorkでリソースメソッドに注釈をつけ、自分のリソースメソッド内に非同期DAO呼び出しを作成するときにNo Hibernate Session bound to thread例外が発生することです。この設計の背後にあるアイデアは、Jerseyリソーススレッドを解放するようにデータベース呼び出しを別のI/Oスレッドで行うことです。

残念ながら例外としてこのRxIoScheduler-2スレッドにはハイバネートセッションがバインドされていません。

提案がありますか?

答えて

0

Hibernate Sessionはスレッドセーフではないため、現在のスレッドの現在のセッションを取得する方法が必要です。そのような戦略はCurrentSessionContextと呼ばれます。

現在のセッションでは、我々は、この呼び出しによって取得したセッションです:

sessionFactory.getCurrentSession() 

Hibernateは様々な現在のセッションの戦略を使用して設定することができます。 @UnitOfWorkは、この戦略使用しています。私たちはSessionはスレッドセーフではない知っているように、だから

ManagedSessionContext.bind(session) 

の明示的な呼び出しによってコンテキストにセッションを置くために、あなたがしなければならない。この戦略の

hibernate.current_session_context_class = managed 

をお別のスレッドのために新しいセッションを作成し、そのセッションをManagedSessionContextに入れるべきです。その後、@UnitOfWorkのエンドポイントメソッドと同じ方法でDAOを呼び出すことができます。 guavaから

public final class HibernateSessionUtils { 

    private HibernateSessionUtils() { 

    } 

    public static void request(SessionFactory factory, Runnable request) { 
     request(factory,() -> { 
      request.run(); 
      return null; 
     }); 
    } 

    public static <T> T request(SessionFactory factory, Supplier<T> request) { 
     Transaction txn = null; 
     Session session = factory.openSession(); 

     try { 
      ManagedSessionContext.bind(session); 
      txn = session.beginTransaction(); 
      T result = request.get(); 
      commit(txn); 
      return result; 
     } catch (Throwable th) { 
      rollback(txn); 
      throw Throwables.propagate(th); 
     } finally { 
      session.close(); 
      ManagedSessionContext.unbind(factory); 
     } 
    } 

    private static void rollback(Transaction txn) { 
     if (txn != null && txn.isActive()) { 
      txn.rollback(); 
     } 
    } 

    private static void commit(Transaction txn) { 
     if (txn != null && txn.isActive()) { 
      txn.commit(); 
     } 
    } 

} 

Throwables

はあなたが別のスレッドのセッションを作成するには、このユーティリティクラスを使用することができます

ManagedSessionContext.unbind(factory) 

でそれを閉じる前に、セッションをアンバインドする必要があります覚えておいてください。

それはあなたがあなたがGuiceを使用して、どこでも工場を注入することができるセッション

sessionFactory.getCurrentSession() 

を得ることができますdao.getCampaigns()方法では、このよう

List<Campaign> getCampaigns(SessionFactory factory, CampaignDao dao) { 
    return HibernateSessionUtils.request(
      factory, 
      dao::getCampaigns 
    ); 
} 

で使用することができます。

その他のオプションはUnitOfWorkAwareProxyFactoryです。