在webapp中使用Spring-Hibernate,线程安全会话管理的策略是什么 [英] Spring-Hibernate used in a webapp,what are strategies for Thread safe session management

查看:92
本文介绍了在webapp中使用Spring-Hibernate,线程安全会话管理的策略是什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用Spring和Hibernate开发一个Web应用程序,并且我非常沉迷于让他的应用程序线程安全并且能够支持基于我老板推荐的重负载,最终我写了会话和会话容器来实现每个请求模式的会话。另外我有很多 DAOs ,而且我不愿意为所有<$ c $写相同的保存方法 c> DAOs 我复制粘贴这个 Hibernate GenericDAO code> (我不能说这是同一回事,因为当时hibernate不属于jboss),并且执行管道工作,并且在压力下,所有这些都变得非常复杂,并且在生产中,是StaleObjectException和重复数据的权利,我有这样的感觉,现在是时候审查我所做的事情,简化它,并使其对大数据处理更健壮。有一件事你应该知道,一个请求涉及到许多DAO。



数据库中有一些石英正在运行。



尽管我希望调整一切,但我没有时间做必要的研究,再加上Hibernate是一种巨大的(学习)。



是吗,我想借你的经验,并问几个问题,知道要采取什么方向。

问题1 :是Hibernate生成的uuid足够安全地用于线程环境并避免StaleObjectException?

问题2 在threadSafe场景中使用hibernate getCurrentSession最好的策略是什么(我已经阅读了threadlocal的东西,但没有太多的理解,所以没有这样做)



问题3 :HIbernateTemplate是否可以用于最简单的解决方案?



问题4 :如果您要为生产服务器实施连接池和调整要求,您会选择什么?



请毫不犹豫地将我指向博客或在线资源,我需要的只是一种适用于我的场景的方法。你的方法,如果你这样做。



感谢您阅读这个,每个人的想法是欢迎... ...

解决方案


我正在用Spring和Hibernate开发一个Web应用程序,并且我非常执着于让应用程序线程安全并能够支持基于我的老板推荐我最终写了我自己的会话和一个会话容器来实现每个请求模式的会话。


您应该放弃所有这些代码并使用Spring / Hibernate API:减少错误,减少维护。
$ b


我复制粘贴这个Hibernate GenericDAO(我不能说它是相同的东西,因为当时hibernate不属于jboss)并且执行管道工作, (...)

您可以使用 GenericDao 并向Spring注入必需的东西。


问题1:是Hibernate生成的uuid足够安全用于线程化环境并避免 StaleObjectException


要严格回答您的问题,是参考指南写的关于uuid生成器的内容:


5。 1.4.1。生成器



...




  • uuid



    使用128位的UUID算法来
    生成类型为字符串
    的标识符网络中唯一(使用
    IP地址)。 UUID是
    ,编码为32位十六进制
    位数的字符串。


所以我认为它是安全的。但我认为你的 StaleObjectException 是不相关的(这是另一个问题)。
$ b


问题2 :在threadSafe场景中使用hibernate getCurrentSession的最佳策略是什么(我已阅读过threadlocal的东西,但没有太多理解,所以没有这样做)


最好的策略是使用它, sessionFactory.getCurrentSession()总会给你一个 Session 作用于当前数据库事务,即上下文会话。再次引用参考文档:


2.5。上下文会话



大多数使用Hibernate的应用程序需要
某种形式的上下文会话,
,其中给定会话有效
在给定的
范围内。但是,跨应用程序
,构成
上下文的定义通常是不同的;
不同的上下文为当前的概念定义了不同的
范围。

版本3.0之前使用Hibernate的应用程序倾向于使用
自行开发的基于ThreadLocal的
上下文会话,助手类
(例如HibernateUtil)或者利用
第三方框架,比如Spring
或者Pico,它们提供了
代理/监听上下文
会话。


(...)

然而,从版本3.1开始,在
SessionFactory.getCurrentSession()
现在可插入。为此,新的
扩展接口
org.hibernate.context.CurrentSessionContext
和一个新的配置参数$ b已添加$ b hibernate.current_session_context_class
以允许定义
当前会话的范围和上下文的可插入性



查看Javadocs的
org.hibernate.context.CurrentSessionContext
接口的详细讨论合约的
。它定义了一个
方法, currentSession(),其中
实现负责跟踪当前上下文
会话。开箱即用的,Hibernate
带有三个
接口的实现: $ c> org.hibernate.context.JTASessionContext

跟踪当前会话,并通过JTA事务处理
作用域。这里的
处理与旧JTA-only方法中的
完全相同。详情请参阅
Javadocs。

  • org.hibernate.context.ThreadLocalSessionContext
    跟踪当前会话由线程
    执行。详情请参阅Javadocs。

  • org.hibernate.context.ManagedSessionContext
    跟踪当前会话由线程
    执行。但是,您是
    负责绑定和解除
    Session实例的静态方法
    对此类:它不会打开,
    flush或关闭会话。



  • (...)


    没有必要实现你自己的 现在基于ThreadLocal 的解决方案,不要这样做。


    问题3 :HIbernateTemplate会为最简单的解决方案做些什么?

    好的, HibernateTemplate 不会被弃用,但不再推荐它,我更喜欢实现 template-less DAOs

      public class ProductDaoImpl implements ProductDao {

    private SessionFactory SessionFactory的;

    public void setSessionFactory(SessionFactory sessionFactory){
    this.sessionFactory = sessionFactory;
    }

    public collectionProductsByCategory(String category){
    return this.sessionFactory.getCurrentSession()
    .createQuery(from test.Product product where product.category =?)
    .setParameter(0,category)
    .list();


    其中 SessionFactory 由Spring注入。我建议阅读所以,如果你仍然使用Spring的HibernateTemplate和/或JpaTemplate ?? 完整的背景以及整个部分 13.3。在ORM数据访问的Spring文档中使用Hibernate。


    问题4:如果您要实现连接池和生产服务器的调优要求?


    嗯...什么?我永远不会实现我的连接池,但使用我的应用程序服务器。也许你应该澄清这个问题。



    更新:在生产中,我不会使用Hibernate内置连接池,而是配置Hibernate来使用一个应用程序服务器提供了JNDI数据源(并因此提供了应用程序服务器连接池)。从文档: $ b


    3.3。 JDBC连接



    ...



    以下是一个示例 <$ c $

      hibernate hibernate.properties   file为应用程序服务器提供了JNDI数据源: .connection.datasource = java:/ comp / env / jdbc / test 
    hibernate.transaction.factory_class = \
    org.hibernate.transaction.JTATransactionFactory
    hibernate.transaction.manager_lookup_class = \
    org.hibernate.transaction.JBossTransactionManagerLookup
    hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect

    从JNDI数据源获取的JDBC连接将自动参与应用程序服务器的容器管理事务。



    I'm developing a web app with Spring and Hibernate and I was so obsessed by making he application thread safe and being able to support heavy load that based on my boss recommendation I end up writing my own session and a session container to implement a session per request pattern. Plus I have a lot of DAOs and me not willing to write the same save method for all the DAOs I copy paste this Hibernate GenericDAO (I can't tell it's the same thing because at the time hibernate wasn't owned by jboss) and do the plumbing stuff, and under pressure, all become quickly complicated and on production, the is StaleObjectException and duplicated data right, and i have the feeling that it's time to review what I've done, simplify it and make it more robust for large data handling. One thing you should know is that one request involves many DAO's.

    There is quartz running for some updates in the database.

    As much as I want to tune everything for the better I lack time to do the necessary research plus Hibernate is kind of huge (learning).

    So this is it, I'll like to borrow your experience and ask for few question to know what direction to take.

    Question 1 : is Hibernate generated uuid safe enough for threading environment and avoiding StaleObjectException?

    Question 2 what are best strategy to use hibernate getCurrentSession in threadSafe scenario (I've read about threadlocal stuff but didn't get too much understanding so didn't do it)

    Question 3 : will HIbernateTemplate do for the simplest solution approach?

    Question 4 : what will be your choice if you were to implement a connection pool and tuning requirement for production server?

    Please do no hesitate to point me to blogs or resources online , all that I need is a approach that works for my scenario. your approach if you were to do this.

    Thanks for reading this, everybody's idea is welcomed...

    解决方案

    I'm developing a web app with Spring and Hibernate and I was so obsessed by making he application thread safe and being able to support heavy load that based on my boss recommendation I end up writing my own session and a session container to implement a session per request pattern.

    You should just drop all this code and use Spring/Hibernate APIs instead: less bugs, less maintenance.

    I copy paste this Hibernate GenericDAO (I can't tell it's the same thing because at the time hibernate wasn't owned by jboss) and do the plumbing stuff, and under pressure, all become quickly complicated (...)

    You can use a GenericDao and inject the required stuff with Spring.

    Question 1: is Hibernate generated uuid safe enough for threading environment and avoiding StaleObjectException?

    To strictly answer your question, here is what Reference Guide writes about the uuid generator:

    5.1.4.1. Generator

    ...

    • uuid

      uses a 128-bit UUID algorithm to generate identifiers of type string that are unique within a network (the IP address is used). The UUID is encoded as a string of 32 hexadecimal digits in length.

    So I consider it as safe. But I think your StaleObjectException are unrelated (it's another problem).

    Question 2: what are best strategy to use hibernate getCurrentSession in threadSafe scenario (I've read about threadlocal stuff but didn't get too much understanding so didn't do it)

    The best strategy is to just use it, sessionFactory.getCurrentSession() will always give you a Session scoped to the current database transaction aka a "contextual session". Again, quoting the Reference Documentation:

    2.5. Contextual sessions

    Most applications using Hibernate need some form of "contextual" session, where a given session is in effect throughout the scope of a given context. However, across applications the definition of what constitutes a context is typically different; different contexts define different scopes to the notion of current. Applications using Hibernate prior to version 3.0 tended to utilize either home-grown ThreadLocal-based contextual sessions, helper classes such as HibernateUtil, or utilized third-party frameworks, such as Spring or Pico, which provided proxy/interception-based contextual sessions.

    (...)

    However, as of version 3.1, the processing behind SessionFactory.getCurrentSession() is now pluggable. To that end, a new extension interface, org.hibernate.context.CurrentSessionContext, and a new configuration parameter, hibernate.current_session_context_class, have been added to allow pluggability of the scope and context of defining current sessions.

    See the Javadocs for the org.hibernate.context.CurrentSessionContext interface for a detailed discussion of its contract. It defines a single method, currentSession(), by which the implementation is responsible for tracking the current contextual session. Out-of-the-box, Hibernate comes with three implementations of this interface:

    • org.hibernate.context.JTASessionContext: current sessions are tracked and scoped by a JTA transaction. The processing here is exactly the same as in the older JTA-only approach. See the Javadocs for details.
    • org.hibernate.context.ThreadLocalSessionContext: current sessions are tracked by thread of execution. See the Javadocs for details.
    • org.hibernate.context.ManagedSessionContext: current sessions are tracked by thread of execution. However, you are responsible to bind and unbind a Session instance with static methods on this class: it does not open, flush, or close a Session.

    (...)

    There is no need to implement your own ThreadLocal-based solution nowadays, don't do that.

    Question 3 : will HIbernateTemplate do for the simplest solution approach?

    Well, the HibernateTemplate is not deprecated but it is not recommended anymore and I prefer to implement template-less DAOs:

    public class ProductDaoImpl implements ProductDao {
    
        private SessionFactory sessionFactory;
    
        public void setSessionFactory(SessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
        }
    
        public Collection loadProductsByCategory(String category) {
            return this.sessionFactory.getCurrentSession()
                    .createQuery("from test.Product product where product.category=?")
                    .setParameter(0, category)
                    .list();
        }
    }
    

    Where the SessionFactory is injected by Spring. I suggest to read So should you still use Spring's HibernateTemplate and/or JpaTemplate?? for complete background and also the whole section 13.3. Hibernate in the Spring documentation on ORM Data Access.

    Question 4 : what will be your choice if you were to implement a connection pool and tuning requirement for production server?

    Hmm... What? I would never implement my connection pool but use the one from my application server. Maybe you should clarify this question.

    Update: In production, I wouldn't use Hibernate built-in connection pool but configure Hibernate to use an application server provided JNDI datasource (and thus the application server connection pool). From the documentation:

    3.3. JDBC connections

    ...

    Here is an example hibernate.properties file for an application server provided JNDI datasource:

    hibernate.connection.datasource = java:/comp/env/jdbc/test
    hibernate.transaction.factory_class = \
        org.hibernate.transaction.JTATransactionFactory
    hibernate.transaction.manager_lookup_class = \
        org.hibernate.transaction.JBossTransactionManagerLookup
    hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
    

    JDBC connections obtained from a JNDI datasource will automatically participate in the container-managed transactions of the application server.

    这篇关于在webapp中使用Spring-Hibernate,线程安全会话管理的策略是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆