2017-10-31 1 views
0

이것이 일반적인 문제라고 생각하지만 일부 검색 후에 관련 항목을 찾을 수 없었습니다.Dropwizard @UnitOfWork 비동기 데이터베이스 호출

내가 겪고있는 문제는 @UnitOfWork과 내 리소스 메서드에 주석을 달고 비동기 DAO 호출을 만드는 내 리소스 메서드 내부에 No Hibernate Session bound to thread 예외가 발생한다는 것입니다. 이 디자인의 배경은 분리 된 I/O 스레드에서 데이터베이스 호출을 작성하여 Jersey 자원 스레드를 비울 수있게하는 것입니다.

예외적으로이 RxIoScheduler-2 스레드에는 최대 절전 모드 세션이 바인딩되어 있지 않습니다.

제안 사항?

답변

0

하이버 네이트 Session은 스레드로부터 안전하지 않으므로 현재 스레드에 대한 현재 세션을 가져 오는 전략이 필요합니다. 이러한 전략을 CurrentSessionContext이라고합니다.

현재의 세션은 우리가이 호출에 의해 얻을 세션 :

sessionFactory.getCurrentSession() 

Hibernate는 다양한 현재 세션 전략을 구성 할 수 있습니다. @UnitOfWork는이 전략을 사용한다 : 우리가 Session는 스레드로부터 안전하지 않습니다 알고, 그래서

ManagedSessionContext.bind(session) 

의 명시 적으로 호출하여 컨텍스트에 세션을 넣어 당신이해야이 전략

hibernate.current_session_context_class = managed 

당신 별도의 스레드에 대한 새 세션을 만들고 해당 세션을 ManagedSessionContext에 두어야합니다. 그 후에는 @UnitOfWork으로 끝점 방법과 동일한 방식으로 DAO를 호출 할 수 있습니다. 당신은 당신은 별도의 스레드에 대한 세션을 만들려면이 유틸리티 클래스를 사용할 수 있습니다

ManagedSessionContext.unbind(factory) 

로를 닫기 전에 세션을 바인딩을 해제해야 염두에

유지 : 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.

는 당신이 당신은 어디서나 Guice를 사용하여 공장을 주입 할 수있는 세션을

sessionFactory.getCurrentSession() 

를 얻을 수있는 dao.getCampaigns() 방법은이 방법

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

사용할 수 있습니다.

다른 옵션은 UnitOfWorkAwareProxyFactory입니다.

관련 문제