休眠 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()的主要内容,如果未能解决你的问题,请参考以下文章
Hibernate中getCurrentSession()与openSession()的区别及应用
getCurrentSession() 与 openSession()
hibernate 的SessionFactory的getCurrentSession 与 openSession() 的区别
hibernate 的SessionFactory的getCurrentSession 与 openSession() 的区别