【问题标题】:"Transaction in view" with Hibernate, Spring, Struts使用 Hibernate、Spring、Struts 的“视图中的事务”
【发布时间】:2011-06-13 04:22:04
【问题描述】:

来自 Hibernate 参考手册: "使用单个数据库事务处理客户端请求,在您打开和关闭 Session 时启动并提交它"

Spring 支持这种模式吗? 我一直在使用带有@Transactional 注释和“在视图中打开会话”模式(org.springframework.orm.hibernate3.support.OpenSessionInViewFilter)的 Spring 事务支持,但事务必须限于服务方法,所以我得到了多个事务每个视图,而不仅仅是一个。

【问题讨论】:

  • 我正在尝试自己学习这种方法。您最终是如何实现的?

标签: hibernate spring transactions struts transactionscope


【解决方案1】:

您可能不想要“视图中的事务”类型的功能。通常,请求发生的情况是

  1. 请求进来
  2. 调用一些将内容保存到数据库的操作
  3. 响应消失。即呈现成功页面或返回 json 或其他任何内容

你不想要'transaction in view'的原因是因为如果在第3步出现错误,你的事务将被回滚,即使实际的业务逻辑是成功的,只是渲染响应失败。

现在,我假设您希望即使在提交数据后出现错误也能提交数据。如果这个假设是错误的,那么好吧,这取决于你。

由于服务方法包含在事务中,可能更简单的解决方案是重构代码,以便每个传入请求调用一个服务。通常这被称为“立面模式”。假设你有

Service1.op1()
Service2.op2()

并且您为一个请求调用这两种方法。您可以简单地创建另一个服务

AppFacade.doOp1andOp2()

在相关服务上调用 op1 和 op2。

另一种可能性是配置 Spring 以使用声明式事务管理将事务放在您的 Struts Actions 周围。请注意事务,从 tx 打开到关闭,所有 db 操作都将使用同一个事务,因此即使您调用多个服务,它们都使用相同的 tx.=。请参阅此处的文档: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html

特别是 10.5.2

但我认为每个业务功能单元使用一个服务调用是最好的方法。

【讨论】:

    【解决方案2】:

    当您使用“在视图中打开会话”模式 (org.springframework.orm.hibernate3.support.OpenSessionInViewFilter) 以在您的 http 呈现(例如 JSP)中启用例如延迟加载,并将其与您的服务方法中 @Transactional 的事务控制混合使用时,那么这在我看来是一种最佳实践方法。

    我这么认为的原因是:

    • 如果您需要在 JSP 中进行延迟加载,那么“Open session in view”是必须的。
    • 事务控制属于您的业务逻辑,因此不能(实际上)由过滤器完成。

    所以至少你需要两者。

    【讨论】:

      【解决方案3】:

      声明一个实现 Hibernate 的 OpenSessionInViewFilter/Interceptor 的类..... 下面给出一个例子...

      import org.hibernate.FlushMode;
      import org.hibernate.Session;
      import org.hibernate.SessionFactory;
      import org.springframework.dao.DataAccessResourceFailureException;
      import org.springframework.orm.hibernate3.support.OpenSessionInViewFilter;
      
      public class CustomHibernateSessionViewFilter extends   OpenSessionInViewFilter {
      
      protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
          Session session = super.getSession(sessionFactory);
          session.setFlushMode(FlushMode.COMMIT);
          return session;
      }
      
      protected void closeSession(Session session, SessionFactory factory) {
          session.flush();
          super.closeSession(session, factory);
      }
      

      }

      在 web.xml(或应用程序上下文)中:-

      <filter>
          <filter-name>OSIVF Filter</filter-name>
          <filter-class>your.path.to.CustomHibernateSessionViewFilter</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>OSIVF Filter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>
      

      希望这能解决您的问题。请让我知道它是否有效。

      【讨论】:

      • 请停止在许多问题上逐字粘贴相同的答案。
      猜你喜欢
      • 1970-01-01
      • 2014-11-23
      • 2012-03-29
      • 1970-01-01
      • 2011-08-22
      • 1970-01-01
      • 2014-11-20
      • 2011-11-01
      • 2011-11-01
      相关资源
      最近更新 更多