为了解耦,service层定义统一返回值,且不向controller抛异常。这样一来,当某个service方法需要做事务处理时。只通过注解声明@Transactional 是不够的。2种解决办法:

1、还需要在catch后,手动回滚TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();。

2、通过将事务逻辑封装为Service的下一层(可以是manager),作为public方法暴露给service,将事务的方法加上spring 注解。

@Transactional("rds")
@MethodLogAnnotation
public ServiceResult<JSONObject> addMerchant(KAMerchantRequest request){
    ServiceResult<JSONObject> result = new ServiceResult();
    try {
        validateAddMerchant(request);
    }catch(AssertException ae) {
        return result.fail(ae.getMessage());
    }

    try {
        MerchantDO merchantDO = request.toMerchantDO();

        //1 插入商户
        merchantDAO.insertKAMerchant(merchantDO);

        //2 插入品牌关联
        List<BrandTargetDO> brandTargetDOList = fillBrandList4Save(request, merchantDO);
        brandTargetDAO.insertBatch(brandTargetDOList);

        //3 插入账户信息
        if(SubjectTypeEnum.getById(request.getMerSubject())!=null) {//签约主体选择了,就必须填入对应的信息
            BankAccountDO bankAccountDO = fillMerchantAccount(request, merchantDO.getId());
            bankAccountDAO.insert(bankAccountDO);
        }
        result.success();
    } catch (Exception e) {
        result.fail("新建商户异常");
        log.error("ka商户管理-新建商户异常-->addMerchant", e);
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }

    return result;
}

 

除以上2点外,还有个地方要注意:

@Service

public class Mxxx {

public void A() {

B();

}

@Transactional

public void B() {}

}

如果一个方法A用了本类的内部方法B,且A方法没有声明@Transactional,此时给B方法加上@Transactional 事务无法生效。

原因是A调用B使用的this,而非spring 上下文context,没有进行事务切面。