Hibernate ThreadLocal会话管理与ForkJoinPool兼容?

时间:2012-04-03 07:56:58

标签: java multithreading hibernate

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

  

线程本地会话模式使用了   java.lang.ThreadLocal类,用于创建可访问的Session   来自单个应用程序线程。这在特别方便   多线程应用程序,例如Web应用程序。

在项目中,我用

实现了这个
<property name="current_session_context_class">thread</property>

hibernate.xml中并使用SessionFactory.getCurrentSession()在我需要的时候进行会话。

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

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

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

提前感谢您的任何答案。

1 个答案:

答案 0 :(得分:4)

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

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

所以,如果你有一个调用sessionFactory.getCurrentSession()的'父'任务,并做了一些事情,然后调用commit(),会话就会关闭,并且没有不适当交互的危险。

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

总而言之,你应该:

  • 如果您从session.close()获得Session,请不要致电.getCurrentSession(),因为CurrentSessionContext负责处理此问题。
  • 在生孩子之前保持忠诚的关系....我的意思是,在产生儿童任务之前打电话给.commit()

作为一个脚注,我发现ThreadLocalSessionContext也是一个有用的读物​​。