【问题标题】:Transaction management for call to two service methods for a single unit of action用于调用单个操作单元的两种服务方法的事务管理
【发布时间】:2011-09-22 11:56:42
【问题描述】:

我们正在重构一个遗留应用程序。旧代码在 Controller 方法中做了这样的事情:

  • 调用 DAO1.update()
  • 调用 DAO2.update()

我们在服务层之间放置了一个中间层,所以上面的代码现在看起来像:

  • 调用Service1.update() --> 调用DAO1.update()
  • 调用Service2.update() --> 调用DAO2.update()

上述两种更新方法中的每一种都被标记为事务性的(使用spring事务)。旧代码不能很好地处理事务——现在,我们希望用户操作(控制器方法)仅映射到单个事务。我们如何使用 Spring 事务本身来实现这一点?

PS:

  1. 我们确实检查了 Hibernate 的 Open Session in View 模式,但是我们 想要一个使用 Spring 事务的解决方案—— 上述情况并不常见,我们担心 OSIV 模式中的性能衰减。
  2. 我们可以将上述两种服务方法组合成一个方法,但我们欢迎使用一种不会妨碍重用的更简洁的情况。

【问题讨论】:

    标签: java spring transactions


    【解决方案1】:

    我们可以将上面的两种服务方法组合成一个方法,但我们会欢迎一种不会妨碍重用的更简洁的情况。

    恕我直言,如果您尝试将这两个服务方法作为一个“工作单元”执行,那么最干净的解决方案是在服务层的@Transactional 方法中调用它们。

    【讨论】:

      【解决方案2】:

      如果您想继续使用@Transactional 注释,那么您肯定必须将您的调用包装在更广泛的注释方法中。因此,您要么定义业务服务,这实际上可能变得非常样板/冗余,要么您使您的控制器的处理方法本身具有事务性(作为@Component,它是一个 Spring 管理的 bean,因此您可以使用@Transactional 也有),或者你定义一个灵活的、通用的、基于回调的模板:

      @Component
      public class TxWorker {
          @Transactional
          public <T> T doInTx(Callable<T> callback) throws Exception {
              return callback.call();
          }
      }
      

      后者的缺点是如果你过度使用它可能会变得有点乱。

      请注意,您可以将 OpenSessionInView 模式和 Spring 管理的事务结合起来,因为 Hibernate 会话(或 JPA entityManager)可能跨越许多 tx(请参阅What is the difference between Transaction-scoped Persistence context and Extended Persistence context?)。但它的主要目标是在渲染视图时提供延迟加载,所以它并不是你想要的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多