当前位置: 首页 > 知识库问答 >
问题:

Spring为@事务性提供的传播行为

方夜洛
2023-03-14
@Controller
public class MyControllerClass{
    @Autowired
    private MyService service;

    public SomeResponse callServiceMethod(SomeRequest reqObj){
         try{
            //lines of codes
            service.serviceMethod(reqObj);
           //lines of codes
        } catch(Exception ex){
            S.O.P("caught inside callServiceMethod of Controller 
            class");
        }
    }


public interface MyService{
    SomeResponse serviceMethod(SomeRequest reqObj);
}


@service
public class MyServiceImpl implements MyService{
    @Autowired
    private EmployeeDAO empDAO;

    @Autowired 
    private PersonDAO personDAO;

    @Autowired 
    private MetadataDAO metaDAO;

    @Transactional(value="transaction_manager_Bean_Name")
    public SomeResponse serviceMethod(SomeRequest reqObj){
         List<Person> personList = ....;//fetch list of person from 
                                         //reqObj
         List<Employee> empList = ......;//fetch list of Employee 
                                         //from reqObj

         SomeHelper someHelper = new SomeHelper(empDAO, personDAO, 
                                          metaDAO);

         try{
            doOperationOnPerson(...);
            doOperationOnEmployee(...);
            doOperationOnMetadata(...);
        } catch(Exception ex){
            S.O.P("caught inside serviceMethod of Impl class");
        }

     }


     @Transactional(value="transaction_manager_Bean_Name")
     public void doOperationOnPerson(List<Person> personList, 
                  List<String> personErrors, SomeHelper someHelper){
        personList.stream().forEach(person ->{
            try{
               someHelper.performTaskOnPerson(person, personErrors);
            } catch(Exception ex){
                  S.O.P("caught inside doOperationOnPerson of Impl 
                  class");
                  personErrors.add(ex.getMessage());
            }
        }
     }

     @Transactional(value="transaction_manager_Bean_Name")
     public void doOperationOnEmployee(List<Employee> empList, 
               List<String> empErrors, SomeHelper someHelper){
        empList.stream().forEach(emp ->{
            try{
               someHelper.performTaskOnEmployee(emp, empErrors);
            } catch(Exception ex){
                 S.O.P("caught inside doOperationOnEmployee of Impl 
                 class");
                 personErrors.add(ex.getMessage());
            }
        }
     }

     @Transactional(value="transaction_manager_Bean_Name")
     public void doOperationOnMetadata(SomeOtherData metadata, 
            List<String> metaDataList, SomeHelper someHelper){
          empList.stream().forEach(emp ->{
             try{
                  someHelper.performTaskOnMetaData(metadata, 
                      metaDataList);
             } catch(Exception ex){
                  S.O.P("caught inside doOperationOnMetadata of Impl 
                  class");
                  personErrors.add(ex.getMessage());
             }
          }
      }
 } 

 public class SomeHelper{
     private PersonDAO personDAO;
     private EmployeeDAO empDAO;
     private MetadataDAO metaDAO;

     SomeHelper(PersonDAO personDAO, EmployeeDAO empDAO, MetadataDAO 
                metaDAO){
          this.personDAO = personDAO;
          this.empDAO = empDAO;
          this.metaDAO = metaDAO;
     }

     @Transactional(value="transaction_manager_Bean_Name", 
                    propagation=Propagation.REQUIRES_NEW)
     public void performTaskOnEmployee(Employee emp, List<String> 
                          empErrors){
          EmpEntity empEntity = empDAO.getEmployee(emp);
          empEntity.setName(...);
         //update other fields
     }

     @Transactional(value="transaction_manager_Bean_Name", 
                    propagation=Propagation.REQUIRES_NEW)
     public void performTaskOnEmployee(Person person, List<String> 
                           personErrors){
          PersonEntity perEntity = personDAO.getPerson(person);
          perEntity.setName(...);
          //update other fields
     }

     @Transactional(value="transaction_manager_Bean_Name", 
                        propagation=Propagation.REQUIRES_NEW)
     public void performTaskOnMetaData(SomeOtherData metadata, 
                                List<String> metaDataList){
        MetaEntity metaEntity = metaDAO.getOther(metadata);
        metaEntity.setName(...);
        //update other fields
    }
}

当somehelper类中的任何方法(将传播行为设置为“requires_new”的事务块)中出现某些异常时,为什么调用方类中不处理它(具有默认传播行为的事务块)?我看到的不是消息“catch inside doOperationMetadata of Impl class”,而是消息“catch inside callServiceMethod of Controller class”。

共有1个答案

华安民
2023-03-14

如果问题是如果基础方法中存在异常,事务回滚是否可以在外部方法中发生,那么对于传播REQUIRES_NEW答案是否定的,因为每个方法都将被视为独立的事务。

引用-@Transactional(传播=传播。必需)和https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html#tx-繁殖

 类似资料:
  • 本文向大家介绍浅谈Spring事务传播行为实战,包括了浅谈Spring事务传播行为实战的使用技巧和注意事项,需要的朋友参考一下 Spring框架提供了事务管理的标准实现,且可以通过注解或者XML文件的方式声明和配置事务。 通过异步事件的方式解耦服务调用,可以提高程序的响应速度,并且避免因为事务传播行为而导致的事务问题。 本文以一个电商平台包裹出库的业务为实际背景,通过异步事件与线程池的方式解耦嵌套

  • 我试图理解Spring事务概念。如下所示,我必须将数据插入两个不同的数据库(iSeries和DB2),但我们的iSeries版本不支持两阶段提交。要求是,只有当两个插入都成功时才应该提交事务,否则应该回滚。 如果我根据需要使用传播或REQUIRES\u NEW,我会得到错误“非法尝试使用现有的两阶段资源提交一阶段资源”。 但是如果我使用NOT_SUPPORTED或支持,它工作正常(即如果其中一个插

  • 所称的刀是: 我希望服务类中的方法在事务中运行,并在方法出现异常时回滚所有内容。但这不是在事务中运行的。 如果我将添加到DAO方法中,那么它看起来就像是在单独的事务中运行的。这是正确的吗?

  • 在下面的文章中说, 在此处输入链接描述 需要传播–支持当前交易;如果不存在,请创建一个新的。 下面是一个产品代码,然后是两个表的产品详细信息。 我的问题是什么时候会发生这种行为?我的意思是,当前交易怎么会结束?是在保存还是更新之后? 如果我们使用PROPAGATION_REQUIRED假设当前事务在插入产品后结束。然后一个新的事务来了,但是如果插入产品数量时出现任何故障,它只会回滚数量而不是输入的

  • 在以下代码方法中,更新正确的sql,但sql有一些问题,但是,当我调用doService()时,它必须将更新提交到DB,即使doService 2()有sql异常,因为doService 2()有一个新的传播类型,但是当我取消这个更新时,不会提交DB。。 正如你们的建议,以以下方式进行测试,但仍然面临相同的问题。这里i在一个单独的类中,但即使仍然存在与上述相同的问题

  • 我正在查看一些现有的代码,并想知道在下面的场景中使用Spring的@Transactional注释会发生什么?考虑以下示例: 下面的updateDataBaseItem()方法是常见的,可以从其他非事务性方法和上面的方法调用: