Hibernate事务和JTA

时间:2016-03-29 11:26:48

标签: java hibernate jta

所以我正在审查几年前我参与的遗留项目。而且我发现了一些困扰我几天的事情。此应用程序使用两个不同的过滤器进行事务处一个名为 HibernateFilter 的过滤器和另一个名为 TransactionFilter 的过滤器(请参阅下面的代码)。

我的问题是: 为什么要使用第二个TransactionFilter?是不是HibernateFilter足够了?

我希望这里有人可以解释这个问题,或者是否有一些我不知道的事情。

HibernateFilter:

     public void doFilter(ServletRequest request,
                       ServletResponse response,
                       FilterChain chain)
      throws IOException, ServletException {
    if (request.getAttribute(FILTER_APPLIED) == null) {
      request.setAttribute(FILTER_APPLIED, FILTER_APPLIED);
      applyFilter(request, response, chain);
    } else {
      chain.doFilter(request, response);
    }
  }

  private void applyFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException {
    try {
      if (sf == null) {
        log.info("SessionFactory assigned from XMLConfig!");
        sf = XMLConfig.getSessionFactory();
      }
      log.debug("Starting a database transaction");
      sf.getCurrentSession().beginTransaction();

      // Call the next filter (continue request processing)
      chain.doFilter(request, response);

      // Commit and cleanup
      log.debug("Committing the database transaction");
      sf.getCurrentSession().getTransaction().commit();

    } catch (Throwable ex) {
      log.error("HibernateFilter, intressting error: " + getRequestUrl(request) + " " + ex, ex);
      // Rollback only
      try {
        log.debug("Trying to rollback database transaction after exception");
        sf.getCurrentSession().getTransaction().rollback();
      } catch (Throwable rbEx) {
        log.error("Could not rollback transaction after exception!", rbEx);
      }

      // Let others handle it... maybe another interceptor for exceptions?
      throw new ServletException(ex);
    }
  }

TransactionFilter:

     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

    // Boot the session!!!
    HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
    HttpSession session = httpServletRequest.getSession(true);
    session.setAttribute(this.getClass().getName(),"Session forced to start!");

    // Start orion transaction...
    Object attribute = servletRequest.getAttribute(FILTER_APPLIED);
    if (attribute == null) {
      servletRequest.setAttribute(FILTER_APPLIED, FILTER_APPLIED);
      applyFilter(servletRequest, servletResponse, filterChain);
    } else {// Skip filter if run more than once for a request.
      filterChain.doFilter(servletRequest, servletResponse);
    }

  }

  private void applyFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException {
    TransactionManager manager = null;
    try {
      manager = (TransactionManager) new InitialContext().lookup("java:comp/UserTransaction");
      if (manager != null) {
        manager.begin();
      }
    } catch (NamingException e) {
      LOG.error("Cant find TransactionManager!", e);
    } catch (SystemException e) {
      LOG.error("Error starting transaction!", e);
    } catch (NotSupportedException e) {
      LOG.error("begin() not supported!", e);
    }
    try {
      filterChain.doFilter(servletRequest, servletResponse);
      if (manager != null) {
        manager.commit();
      }
    } catch (Exception e) {
      try {
        if (manager != null) {
          manager.rollback();
          // Let others handle the rest... maybe another interceptor for exceptions?
          throw new ServletException(e);
        }
      } catch (SystemException e1) {
        LOG.error("Couldn't rollback!", e1);
      }
    }

1 个答案:

答案 0 :(得分:0)

为什么这样做有不同的选择,其中大多数只是当时没有人知道它。

但至少我可以给你一个部分有意义的场景。但在此之前我做了一些hibernate / JPA / JTA基础知识。

  1. Hibernate ,尤其是 SessionFactory 是一种仅仅是hibernate的机制,不属于java标准。这就是您的团队用于与hibernate相关的交互。
  2. JPA 是关于对象关系映射的java标准,它在很大程度上受到了hibernate的启发。与JPA结合使用的更常见的是 EntityManager EntityManagerFactory 。这可以与hibernate结合使用,因为 Hibernate 标准实现。在大多数情况下,您可以使用Hibernate Session和EntityManager启动事务提交。
  3. JTA Java Transaction API 。这只是处理应用程序中的事务的标准。 @Transactional注释是此规范的一部分,经常与JPA实现结合使用。这两个标准旨在协同工作。不能同时使用EntityManager和JTA规范中的事务管理(如果我没记错的话)。但除了与JPA结合使用外,此规范不仅限于JPA或数据库。此标准还可用于确保 JMS资源的事务处理。基本上任何正确实施标准的东西都可以“交易”处理。只要把它看成是一个数据源,无论它是什么。
  4. 让我们了解它的使用原因。我假设有一个应用程序服务器在使用,其中配置了数据源并处理事务。例如JMS资源。另一方面,他们希望将hibernate用作持久性提供程序。现在有不同的选择,为什么他们不使用基于JPA的数据源和hibernate作为持久性提供程序。一个是应用程序服务器具有捆绑的JPA实现,团队无法否决/替换它。另一个是他们想要使用不属于JPA规范的hibernate自定义功能,并且他们无法将其与JPA方式结合使用。

    总结一下,有很多选择,我的答案很多猜测,但我希望它至少有一点帮助。