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

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

  1. hibernate.current_session_context_class 的值应该是多少?

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

     Session s = HibernateUtil.getSessionFactory().openSession();
     Session s = HibernateUtil.getSessionFactory().getCurrentSession()
    
  3. 最后,“每个 Web 应用一个会话”或“每个请求一个会话”哪个更好?

【问题讨论】:

    标签: java hibernate


    【解决方案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 相关的问题。你能帮我解决吗 - stackoverflow.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 应用程序。

      【讨论】:

        猜你喜欢
        • 2015-11-12
        • 2011-04-17
        • 2016-04-20
        • 2016-12-21
        • 2015-03-20
        • 1970-01-01
        • 2012-12-10
        • 2012-07-06
        • 1970-01-01
        相关资源
        最近更新 更多