Spring-Hibernate在webapp中使用,什么是Thread安全会话管理的策略

我正在使用Spring和Hibernate开发一个Web应用程序,我非常着迷于使应用程序线程安全并能够支持基于我的老板建议的重负载我最终编写自己的sessionsession container来实现session per request pattern 。 另外我有很多DAOs而且我不愿意为所有DAOs编写相同的save method我复制粘贴这个Hibernate GenericDAO (我不能说它是同样的事情,因为当时hibernate不归jboss所有)和做管道工作,并且在压力下,所有这些都变得很复杂,并且在生产中,StaleObjectException和重复的数据是正确的,我觉得是时候回顾我已经完成的工作,简化它并使其更加强大数据处理。 你应该知道的一件事是,一个请求涉及许多DAO。

有石英运行数据库中的一些更新。

尽管我想要更好地调整一切,但我没有时间做必要的研究,而Hibernate则是一种巨大的(学习)。

所以就是这样,我想借用你的经验并提出一些问题来了解要采取的方向。

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

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

问题3 :HIbernateTemplate会采用最简单的解决方案吗?

问题4 :如果要实现连接池并调整生产服务器的需求,您会选择什么?

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

感谢您阅读本文,欢迎大家的想法……

我正在使用Spring和Hibernate开发一个Web应用程序,我非常着迷于使应用程序线程安全并能够支持基于我的老板建议的重负载我最终编写自己的会话和会话容器来实现会话每个请求模式。

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

我复制粘贴这个Hibernate GenericDAO(我不能说它是同样的东西,因为当时hibernate不归jboss所有)并且做了管道的东西,并且在压力下,所有都变得很快复杂(…)

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

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

要严格回答您的问题,以下是参考指南中有关uuid生成器的内容:

5.1.4.1。 发电机

  • uuid

    使用128位UUID算法生成在网络中唯一的字符串类型的标识符(使用IP地址)。 UUID编码为长度为32个hex数字的字符串。

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

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

最好的策略是使用它, sessionFactory.getCurrentSession()将始终为您提供一个作用于当前数据库事务的会话,即“上下文会话”。 再次引用参考文档:

2.5。 上下文会话

大多数使用Hibernate的应用程序需要某种forms的“上下文”会话,其中给定的会话在给定上下文的范围内有效。 但是,跨应用程序,构成上下文的定义通常是不同的; 不同的上下文定义了当前概念的不同范围。 使用Hibernate 3.0版之前的应用程序倾向于使用本土的基于ThreadLocal的上下文会话,辅助类(如HibernateUtil),或利用第三方框架(如Spring或Pico),它们提供基于代理/拦截的上下文会话。

(……)

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

有关其合同的详细讨论,请参阅org.hibernate.context.CurrentSessionContext接口的Javadocs。 它定义了一个方法currentSession() ,通过该方法,实现负责跟踪当前的上下文会话。 开箱即用,Hibernate附带了这个界面的三个实现:

  • org.hibernate.context.JTASessionContext :当前会话由JTA事务跟踪和确定范围。 此处的处理与旧的仅JTA方法完全相同。 有关详细信息,请参阅Javadocs。
  • org.hibernate.context.ThreadLocalSessionContext :当前会话由执行线程跟踪。 有关详细信息,请参阅Javadocs。
  • org.hibernate.context.ManagedSessionContext :当前会话由执行线程跟踪。 但是,您有责任使用此类上的静态方法绑定和取消绑定Session实例:它不会打开,刷新或关闭会话。

(……)

现在不需要实现自己的基于ThreadLocal的解决方案,不要那样做。

问题3 :HIbernateTemplate会采用最简单的解决方案吗?

好吧, HibernateTemplate并没有被弃用,但我不再推荐它了,我更喜欢实现无模板的DAO :

 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(); } } 

SessionFactory由Spring注入的地方。 我建议阅读所以你还应该使用Spring的HibernateTemplate和/或JpaTemplate吗? 完整的背景和整个13.3节。 关于ORM数据访问的Spring文档中的Hibernate 。

问题4:如果要实现连接池并调整生产服务器的需求,您会选择什么?

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

更新:在生产中,我不会使用Hibernate内置连接池,而是将Hibernate配置为使用应用程序服务器提供的JNDI数据源(以及应用程序服务器连接池)。 从文档:

3.3。 JDBC连接

以下是提供JNDI数据源的应用程序服务器的示例hibernate.properties文件:

 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 

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