【问题标题】:Hibernate ThreadLocal Session management compatible with ForkJoinPool?Hibernate ThreadLocal Session 管理兼容 ForkJoinPool?
【发布时间】:2012-04-16 20:56:42
【问题描述】:

我通常在 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 使用较少数量的线程,并在其他任务处于休眠状态时在正在运行的任务之间共享它们。 (出于拖延/烦人的“事务连接中的任务”的动机,)我想在一个工作单元之后关闭()每个休眠会话。

所以.. 当我在任务结束时调用 HibernateSessionFactory.getThreadLocalSession().close() - 并且任务在 ForkJoinPool 中运行 - 会出现问题吗?我应该放弃 ThreadLocal 模式以进行大量并行计算并自己管理会话吗?

提前感谢您的任何回答。

【问题讨论】:

  • 您是使用 SessionFactory.getCurrentSession() 还是 .openSession() 来获取您的 Session 对象?如果 getCurrentSession,您使用的是什么 CurrentSessionContext?我猜是 ThreadLocalSessionContext,但您将其称为“模式”而不是类。
  • 感谢您对此进行调查。我更详细地更新了问题。

标签: java multithreading hibernate


【解决方案1】:

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

ForkJoinPool (javadocs) 用于任务产生其他任务(fork)并等待它们完成(join)的情况。在等待期间,正在执行父任务的线程可能会被重新用于执行子任务。根据ThreadLocalSessionContext 的javadocs,当您提交从中获得的事务时,Session 将被关闭(即每个Session 只有一个事务)。

因此,如果您有一个调用 sessionFactory.getCurrentSession() 的“父”任务,并执行一些操作,然后调用 commit(),则 Session 将关闭并且不存在不当交互的危险。

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

总之,你应该:

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

作为脚注,我发现this wiki page 对这个主题也很有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-25
    • 2019-11-23
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-08
    相关资源
    最近更新 更多