&引用;“交易在望”;使用Hibernate、Spring和Struts

&引用;“交易在望”;使用Hibernate、Spring和Struts,hibernate,spring,transactions,struts,transactionscope,Hibernate,Spring,Transactions,Struts,Transactionscope,从Hibernate参考手册: 使用单个数据库事务为客户端请求提供服务,在打开和关闭会话时启动并提交该请求 Spring支持这种模式吗? 我一直在使用Spring事务支持@Transactional注释和“视图中打开会话”模式(org.springframework.orm.hibernate3.support.OpenSessionInViewFilter),但事务必须限于服务方法,因此我在每个视图中获得多个事务,而不仅仅是一个。使用“视图中打开会话”时模式(org.springframewo

从Hibernate参考手册: 使用单个数据库事务为客户端请求提供服务,在打开和关闭会话时启动并提交该请求

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

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

我这样认为的原因是:

  • 如果您需要在JSP中延迟加载,那么“在视图中打开会话”是一个实际的必需
  • 事务控制属于您的业务逻辑,因此它不能(实际上)由过滤器完成

因此,至少您需要这两种功能。

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

  • 请求进来了
  • 调用一些将内容保存到数据库的操作
  • 反应出来了。i、 e.呈现成功页面或返回json或其他内容
  • 您不希望看到“transaction in view”的原因是,如果在步骤3中出现错误,您的事务将回滚,即使实际业务逻辑成功,只会导致响应失败

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

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

    Service1.op1()
    Service2.op2()
    
    您可以为一个请求调用这两个方法。您可以简单地创建另一个服务

    AppFacade.doOp1andOp2()
    
    调用相关服务上的op1和op2

    另一种可能是配置Spring,使用声明式事务管理将事务放在Struts操作周围。注意,对于事务,从tx打开到关闭,所有db操作都将使用相同的事务,因此即使您调用多个服务,它们都使用相同的tx。请参阅此处的文档:

    特别是10.5.2

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

    声明一个实现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(或应用程序上下文)中:-

    
    OSIVF滤波器
    您的.path.to.CustomHibernateSessionViewFilter
    OSIVF滤波器
    /*
    

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

    请停止在许多问题上一字不差地粘贴相同的答案。我正在尝试自己学习这种方法。您最终是如何实现这一点的?
    <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>