Sping为@transactional提供的传播行为

时间:2018-07-26 16:07:40

标签: transactional propagation

@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'的事务块)中发生任何异常时,为什么没有在调用者类中对其进行处理(具有具有默认传播行为的事务块)?而不是看到消息“夹在Impl类的doOperationOnMetadata内部”,而是收到消息“夹在Controller类的callServiceMethod内部”。

1 个答案:

答案 0 :(得分:0)

如果问题在于在外部方法是否可以在外部方法上发生事务回滚,那么底层方法是否存在异常,则对于Propagation为REQUIRES_NEW的回答是否定的,因为每种方法都将被视为独立事务。

参考-@Transactional(propagation=Propagation.REQUIRED)https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html#tx-propagation