事务管理,用于调用单个操作单元的两种服务方法

时间:2011-09-22 11:56:42

标签: java spring transactions

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

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

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

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

上述两种更新方法中的每一种都已标记为事务性(使用spring事务)。旧代码没有很好地处理事务 - 现在,我们希望用户操作(控制器方法)仅映射到单个事务。我们如何使用弹簧交易本身实现这一目标?

PS:

  1. 我们在View模式中检查了Hibernate的Open Session,但是我们 想要一个利用Spring事务的解决方案 - 以上情景并不常见,我们担心 OSIV模式中的性能衰退。
  2. 我们可以将上述两种服务方法合并为一种方法,但欢迎使用一些不会妨碍重复使用的情况。

2 个答案:

答案 0 :(得分:4)

  

我们可以将上面的两种服务方法合并到一个方法中,但是会欢迎一些不会妨碍重用的清洁情况。

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

答案 1 :(得分:3)

如果您想继续使用@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?)。但它的主要目标是在渲染视图时提供延迟加载,因此它并不是您正在寻找的。