在分层的 Spring MVC Web 应用程序中处理休眠会话的最佳方式

2022-09-04 19:41:07

如果我们有一个Web应用程序,它有

  • heavy UI (Spring MVC + JQuery with JSON)
  • 休眠,JPA 注释是域模型
  • 将 Spring 提供的 DAO 扩展到 DAO 层的代码
  • JBOSS是应用程序服务器,Oracle作为后端
  • 基于数据源 (JNDI) 的连接池(不是 XA,而是本地数据源)
  • 还可以访问多个数据源(处理多个数据库)

从行为上讲,大量的数据检索(70%)和30%
的数据更新对于以下有效使用数据库连接并确保连接使用时没有太多泄漏的最佳实践是什么?

  1. 选择基于休眠模板的DAO会更好吗?
  2. 什么样的事务管理器是可以建议的,我们应该选择基于AOP的事务管理在哪里
  3. 在何处实例化会话,以及在何处关闭会话以有效使用来自连接池的连接。
  4. 确实,我们需要从服务层处理事务,但是会话会发生什么,它们会等待更长的时间(我们没有使用任何opensessioninviewFilter)
  5. 哪个层更适合处理选中的异常(业务异常)和运行时异常。

很抱歉这是一个有点长的问题,但是我看到这是一个常见的查询,我尝试合并它。感谢您的耐心和指导。感谢您的帮助。


答案 1

这听起来像是一个非常典型的Spring/Hibernate应用程序,所以我建议遵循当前的最佳实践,我最近在另一个答案中概述了这一点。具体说来:

  1. 不要扩展Spring DAO支持类或使用HibernateTemplate。使用@Repository注释与组件扫描相结合,并将SessionFactory直接注入DAO。
  2. 使用Spring的HibernateTransactionManager,并且绝对使用通过@Transactional的声明性事务管理作为默认方法。
  3. Spring管理它。默认情况下,它将及时打开会话以进行事务,但更喜欢由Spring的OpenSessionInViewFilter启用的打开会话中的视图模式
  4. 请参阅 #3。
  5. 始终在应该处理异常的位置处理异常 - 换句话说,这是一个设计决策。但是,请注意,默认情况下,Spring 事务框架会在未选中的异常(但未选中)时回滚,以匹配 EJB 规范的行为。确保在使用已检查异常的任何位置设置正确的回滚规则(请参阅上一个链接)。

此外,显然,使用连接池。Apache Commons DBCP是一个很好的选择。“连接使用中没有太多泄漏”是不够的。您必须具有零连接泄漏。依靠Spring来管理您的资源将有助于确保这一点。至于任何其他性能问题,请不要过早地尝试优化。等到你看到你的问题区域在哪里,然后找出单独解决每个问题的最佳方法。由于您的瓶颈很可能与数据库相关,请查看Hibernate参考的性能章节,以了解您面临的问题。它涵盖了缓存和获取策略的重要概念。


答案 2
  • 直接在 DAO 中使用 JPA。确保不要将其标记为扩展EntityManager
  • 首选和 - 仅在服务层上<tx:annotation-driven />@Transactional
  • 事务管理器还会打开和关闭会话(如果线程中尚不存在会话)。在这里,很高兴知道会话是每个请求的会话。每个请求(=线程)都有一个单独的会话实例。但是,仅当需要数据库连接时才会创建数据库连接,因此即使所有方法周围都有事务管理器,也不会打开不必要的连接。
  • 只读事务 - 在仅进行数据检索的情况下使用@Transactional(readOnly=true)
  • 缓存 - 利用休眠第二级缓存将实体放入内存中(而不是每次都从数据库获取它们)
  • 避免和懒惰的集合。这是主观的,但在我看来,所有离开服务层的对象都必须初始化。对于小型集合(例如角色列表),您可以拥有预先收集的集合。对于较大的集合,请使用 HQL 查询。OpenSessionInView

推荐