首页 文章

Hibernate ThreadLocal会话管理与ForkJoinPool兼容?

提问于
浏览
7

我通常在Java Web项目中使用Hibernate ThreadLocal会话管理模式:

线程本地会话模式利用java.lang.ThreadLocal类创建可从单个应用程序线程访问的Session . 这在多线程应用程序(例如Web应用程序)中特别方便 .

在我实施的项目中

<property name="current_session_context_class">thread</property>

hibernate.xml 并使用 SessionFactory.getCurrentSession() 在我需要的时候获取会话 .

现在我有一个程序是 not 一个Servlet,但它做了大量的并行计算和数据库交互 .

我想用ForkJoinPool实现它 . 现在我想知道在这种情况下使用Hibernate ThreadLocal会话管理是否有误 . 据我所知,ForkJoinPool使用较少数量的线程,并在正在运行的任务之间共享它们,而其他任务正在休眠 . (由于在事务'连接中停止/烦人的“任务”,我想在一个工作单元之后关闭()每个Hibernate会话 .

所以..当我在我的任务结束时调用HibernateSessionFactory.getThreadLocalSession() . close()并且任务在ForkJoinPool中运行时 - 会出现麻烦吗?我应该删除ThreadLocal模式以进行大量并行计算并自行管理Sessions吗?

提前感谢您的任何答案 .

1 回答

  • 4

    使用 ThreadLocalSessionContext 对您来说可能会有问题,但这取决于您的任务正在做什么 .

    ForkJoinPooljavadocs)适用于任务产生其他任务(fork)并等待它们完成(连接)的情况 . 在等待时,可以重新使用正在执行父任务的线程来执行子任务 . 根据ThreadLocalSessionContext的javadocs, Session 在你提交一个事务时会被关闭(即每个 Session 只有一个事务) .

    所以,如果你有一个调用 sessionFactory.getCurrentSession() 的'parent'任务,并做了一些事情,那么调用commit(),会话关闭,不存在不适当交互的危险 .

    但是,如果在调用 .getCurrentSession() 之后生成子任务并且在调用 .commit() 之前,则可能会遇到问题,因为其他任务可能在此线程上执行,而 .getCurrentSession() 将返回父任务使用的会话 . 这几乎肯定不是你想要的,因为孩子们的任务可能应该是彼此做同样的事情,你不会想要一个人与父母任意分享 Session 状态,而其他人则不这样做 .

    总而言之,您应该:

    • 如果从 .getCurrentSession() 获得 Session ,则不调用 session.close() ,因为 CurrentSessionContext 负责处理 .

    • 在生孩子之前保持忠诚的关系....我的意思是,在产生儿童任务之前调用 .commit() .

    作为一个脚注,我发现this wiki page也是一个有用的读物 .

相关问题