带有涉及两个 DAO 的遗留代码的 Spring 事务

Posted

技术标签:

【中文标题】带有涉及两个 DAO 的遗留代码的 Spring 事务【英文标题】:Spring transaction with legacy code involving two DAOs 【发布时间】:2020-05-18 17:36:56 【问题描述】:

我正在使用一些遗留代码,其中所有 Spring DAO 都使用 @Transactional 注释进行了注释。 现在我有一个业务需求,我需要在我的服务层中调用两个不同的 DAO,并在事务在任何时候失败时回滚事务。

如何在 Spring 5 中实现这一点,而无需从 DAO 中删除 @Transactional 注释并仍然从服务层使用它们。我认为下面的代码不会起作用,因为每个 DAO 中的事务将彼此独立。

非常感谢。

@Transactional
public FooDao 


@Transactional
public BarDao 



@Transactional
public TestServiceImple implements TestService 
  fooDao.action1();
  barDao.action2();

【问题讨论】:

【参考方案1】:
    @Transactional 注释的默认propagation 类型是Propagation.REQUIRED。

支持当前事务,如果不存在则创建一个新事务。

    @Transactional 注释的默认rollback 行为如下

默认情况下,事务将在 RuntimeException 和 错误但不在检查异常(业务异常)上。

这两个默认配置将确保 TestServiceImple 中的 fooDao.action1()barDao.action2() 使用相同的 txn 并在服务层的任何 RuntimeException/自定义回滚配置上一起回滚,前提是这两个方法是从使用 @Transactional 注释的相同服务方法。

例子

 @Transactional
 public TestServiceImple implements TestService 

     public void callDaoMethods()
      fooDao.action1();
      barDao.action2();
     

 

public TestServiceImple implements TestService 

 @Transactional
 public void callDaoMethods()
   fooDao.action1();
   barDao.action2();
 

【讨论】:

这个也很有用:***.com/questions/5684473/…【参考方案2】:

@Transaction 中默认使用 Propagation.REQUIRED,第二种方法将使用当前事务。 @Transactional(propagation=Propagation.REQUIRED),所以最终它只会进行一笔交易。

【讨论】:

【参考方案3】:

如果您的总体目标是确保事务将回滚通过两个 dao 调用所做的更改,那么当引发未经检查的异常时,您应该能够从 dao 方法本身中删除 @Transactional,并将其保留在服务层中. Spring 中的事务可以是类或方法级别,因此在这种情况下,您可以只在调用两个 dao 方法的方法*上使用它(尽管,正如您所指出的,您似乎希望将这些注释保留在 dao 层中?) .

事务的一般要点之一是在处理多个数据库更改(对 dao 的多次调用)时,因此在单个 dao 方法(或一般的 dao 层)上具有事务注释并不是一个很好的设计)。

如果你是两个 daos 处理两个不同的数据源(不确定,你没有提到)那么,如果你有/可以获取 spring 数据作为依赖项,你可以利用 ChainedTransactionManager (https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/transaction/ChainedTransactionManager.html)

【讨论】:

以上是关于带有涉及两个 DAO 的遗留代码的 Spring 事务的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 测试:无法实例化内部配置类

将遗留应用程序迁移到 Symfony2

注入 DAO 的 @Transactional 的 Spring WS 拦截器不起作用

Spring 3,带有通用 DAO 的 Hibernate 4 AutoWired sessionFactory

带有 ApplicationContext.xml、DAO 和 Service 的 Spring JPA 为 NULL

从 Servlet 和 JDBC 迁移到 DAO 和 Spring,建议?