我认为这是一个常见问题,但经过一番搜索后我找不到任何相关内容。
我遇到的问题是,当使用 @UnitOfWork
注释我的资源方法并在我的资源方法内部时,我得到了一个 No Hibernate Session bound to thread
异常, 进行异步 DAO 调用。此设计背后的想法是在单独的 I/O 线程上进行数据库调用,以便释放 Jersey 资源线程。
不幸的是,如异常所述,此 RxIoScheduler-2
线程没有绑定(bind) hibernate session 。
有什么建议吗?
最佳答案
Hibernate Session
不是线程安全的,所以我们需要一个策略来获取当前线程的当前 session 。这种策略称为 CurrentSessionContext
。
当前 session 是我们通过这个调用得到的 session :
sessionFactory.getCurrentSession()
Hibernate 可以配置各种当前 session 策略。 @UnitOfWork
使用此策略:
hibernate.current_session_context_class = managed
对于此策略,您应该通过显式调用
将 session 置于上下文中ManagedSessionContext.bind(session)
因此,正如我们所知,Session
不是线程安全的,您应该为单独的线程创建一个新 session 并将该 session 放入 ManagedSessionContext
中。之后,您可以通过与使用 @UnitOfWork
的端点方法相同的方式调用您的 DAO。
请记住,您应该在关闭 session 之前取消绑定(bind)
ManagedSessionContext.unbind(factory)
您可以使用此实用程序类为单独的线程创建 session :
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();
}
}
}
来自 guava
的 Throwables
。
可以这样使用
List<Campaign> getCampaigns(SessionFactory factory, CampaignDao dao) {
return HibernateSessionUtils.request(
factory,
dao::getCampaigns
);
}
在dao.getCampaigns()
方法中可以获取session
sessionFactory.getCurrentSession()
您可以使用 Guice
在任何地方注入(inject)工厂。
其他选项是使用 UnitOfWorkAwareProxyFactory
。
关于java - 具有异步数据库调用的 Dropwizard @UnitOfWork,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47027268/