休眠 openSession() 与 getCurrentSession()

Posted

技术标签:

【中文标题】休眠 openSession() 与 getCurrentSession()【英文标题】:Hibernate openSession() vs getCurrentSession() 【发布时间】:2011-12-24 04:53:04 【问题描述】:

我有一些关于在 JSP Web 应用程序中使用 Hibernate 的问题。

    hibernate.current_session_context_class 的值应该是多少?

    那么,应该使用以下哪个语句?为什么?

     Session s = HibernateUtil.getSessionFactory().openSession();
     Session s = HibernateUtil.getSessionFactory().getCurrentSession()
    

    最后,“每个 Web 应用一个会话”或“每个请求一个会话”哪个更好?

【问题讨论】:

【参考方案1】:

正如本论坛post 中所解释的,1 和2 是相关的。如果您将 hibernate.current_session_context_class 设置为线程,然后实现类似 servlet 过滤器来打开会话 - 那么您可以使用 SessionFactory.getCurrentSession() 在其他任何地方访问该会话。

SessionFactory.openSession() 总是会打开一个新会话,一旦您完成操作就必须关闭该会话。 SessionFactory.getCurrentSession() 返回一个绑定到上下文的会话 - 你不需要关闭它。

如果您使用 Spring 或 EJB 来管理事务,您可以将它们配置为与事务一起打开/关闭会话。

你不应该使用one session per web app - session 不是线程安全的对象 - 不能被多个线程共享。您应该始终使用“每个请求一个会话”或“每个事务一个会话”

【讨论】:

非常感谢@gkamal。我查看Open Session in View 文档中的代码。 (您的链接指向该文档。)作者建议使用过滤器。在他的过滤器代码中,他没有调用openSession()close()。他只打电话给getCurrentSession()。我猜他将current_session_context 设置为thread。现在我想我明白了getCurrentSession()。但是,我不知道什么时候应该使用openSession() 如果您不希望会话绑定到任何上下文,您将使用 OpenSession。在某些情况下,您需要一个不同的会话 - 除了绑定到上下文的会话(Hibernate 拦截器有一个限制,您不能使用原始会话) - 在这些情况下,您将使用 OpenSession 而不是 currentSession。 OpenSession 创建一个新会话,您必须明确关闭它。例如,在 DAO 方法中,您将调用 OpenSession - 使用该会话并关闭它。 我正在使用 getCurrentSession();因为我在侦听器中初始化它而不是过滤器,从您的角度来看,这可以吗?我正在使用 mvc2 jsp servlet @gkamal - 我有一个与Sessions 相关的问题。你能帮我解决吗 - ***.com/questions/23351083/… 。谢谢你和chenqui。 IMO,最好让每个线程拥有自己的 Session,并且只有一个 Session,对吧?【参考方案2】:

如果我们谈论 SessionFactory.openSession()

它总是创建一个新的 Session 对象。 您需要显式刷新和关闭会话对象。 在单线程环境中,它比 getCurrentSession() 慢。 您无需配置任何属性即可调用此方法。

如果我们谈论 SessionFactory.getCurrentSession()

如果不存在,则创建一个新会话,否则使用当前休眠上下文中的相同会话。 您不需要刷新和关闭会话对象,它会由 Hibernate 内部自动处理。 在单线程环境中,它比 openSession() 更快。 您需要配置其他属性。 "hibernate.current_session_context_class" 调用getCurrentSession()方法,否则会抛出异常。

【讨论】:

上面的答案告诉不要每个 webapp 使用单个会话。因此,如果我使用getCurrentSession,它会重用相同的会话,不是吗?【参考方案3】:

openSession:当你调用SessionFactory.openSession时,它总是会创建一个新的Session对象并把它交给你。

您需要显式刷新和关闭这些会话对象。

由于会话对象不是线程安全的,因此您需要在多线程环境中为每个请求创建一个会话对象,在 Web 应用程序中也为每个请求创建一个会话。

getCurrentSession:当你调用SessionFactory.getCurrentSession时,它会为你提供处于休眠上下文中并由休眠内部管理的会话对象。绑定事务范围。

当您调用SessionFactory.getCurrentSession 时,如果它不存在,它会创建一个新的Session,否则使用当前休眠上下文中的相同会话。它会在事务结束时自动刷新并关闭会话,因此您无需在外部进行。

如果你在单线程环境下使用hibernate,你可以使用getCurrentSession,与每次创建一个新会话相比,它的性能更快。

您需要将以下属性添加到 hibernate.cfg.xml 以使用getCurrentSession 方法:

<session-factory>
    <!--  Put other elements here -->
    <property name="hibernate.current_session_context_class">
          thread
    </property>
</session-factory>

【讨论】:

servlet 不会为每个请求打开一个新线程吗?因此,如果它是一个 Java webapp,它已经不是一个单线程环境了?【参考方案4】:
+----------------------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
| Parameter            |                                openSession                                 |                                          getCurrentSession                                          |
+----------------------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
| Session  creation    | Always open new session                                                    | It opens a new Session if not exists , else use same session which is in current hibernate context. |
+----------------------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
| Session close        | Need to close the session object once all the database operations are done | No need to close the session. Once the session factory is closed, this session object is closed.    |
+----------------------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
| Flush and close      | Need to explicity flush and close session objects                          | No need to flush and close sessions , since it is automatically taken by hibernate internally.      |
+----------------------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
| Performance          | In single threaded environment , it is slower than getCurrentSession       | In single threaded environment , it is faster than openSession                                      |
+----------------------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+
| Configuration        | No need to configure any property to call this method                      | Need to configure additional property:                                                              |
|                      |                                                                            |  <property name=""hibernate.current_session_context_class"">thread</property>                       |
+----------------------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------+

【讨论】:

【参考方案5】:

SessionFactory:“每个数据库每个应用程序一个 SessionFactory” ( 例如。, 如果您在我们的应用程序中使用 3 个数据库,则需要为每个数据库创建 sessionFactory 对象,总共需要创建 3 个 sessionFactory。否则,如果您只有一个数据库,一个 sessionfactory 就足够了 )。

会话:“一个请求-响应周期的一个会话”。您可以在请求到来时打开会话,并在请求过程完成后关闭会话。 注意:-不要将一个会话用于 Web 应用程序。

【讨论】:

以上是关于休眠 openSession() 与 getCurrentSession()的主要内容,如果未能解决你的问题,请参考以下文章

休眠 session.save() 总是返回 1

获取休眠中实体的最后一个ID

Hibernate中getCurrentSession()与openSession()的区别及应用

getCurrentSession() 与 openSession()

hibernate 的SessionFactory的getCurrentSession 与 openSession() 的区别

hibernate 的SessionFactory的getCurrentSession 与 openSession() 的区别