为了解耦,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,没有进行事务切面。