项目实战--@Transactional 的使用

江枫思渺然 提交于 2019-11-27 18:13:55

@Transactional 介绍  

  Spring 事务管理分为编码式和声明式的两种方式,编程式事务指的是通过编码方式实现事务;声明式事务基于 AOP,将具体业务逻辑与事务处理解耦。@Transactional属于声明式事务中(两种)的一种,另一种是通过在配置文件(xml)中做相关的事务规则声明。我这里就不解释@Transactional注解管理事务的实现步骤了,直接用项目实战的例子说明为什么要用到@Transactional。

需求说明

  公司项目中的合同表的信息是通过第三方接口传数据,我需要写一个合同数据的保存接口,合同表中有一个是合同主表,另一个是合同明细表,明细表中冗余了合同主表的id。对于数据的保存肯定得保证完整性,不能有遗漏,必须全部保存,如果保存的过程中有报错就不能执行保存操作,这时@Transactional就起到作用了,它能够保证合同信息及其明细信息完整的保存。

@Override@Transactional(transactionManager = "userDataSourceTxManager")public Long addSingleContractInfo(AddContractInfoReqDto addContractInfoReqDto) {
    if(null==addContractInfoReqDto){
        throw new BizException(ExampleExceptionCode.REQ_PARAM_NON_NULL.getMsg());
    }
    //保存合同主表信息
    ContractEo contractEo = ContractEo.newInstance();
    DtoHelper.dto2Eo(addContractInfoReqDto,contractEo);
    contractEo.setUpdateTime(addContractInfoReqDto.getUpdateDate());
    contractDas.insert(contractEo);
    //保存合同商品详情信息
    List<ContractItemDetailReqDto> itemDetailReqDtos = addContractInfoReqDto.getItemDetailReqDtoList();
    itemDetailReqDtos.stream().forEach(dto->{        ContractItemDetailEo contractItemDetailEo= ContractItemDetailEo.newInstance();
        DtoHelper.dto2Eo(dto,contractItemDetailEo);
        //合同商品明细表中冗余主表id
        contractItemDetailEo.setUsContractId(contractEo.getId());
        contractItemDetailDas.insert(contractItemDetailEo);
    });
    return contractEo.getId(); }

注意事项

  第二条红色标注的新建合同明细实体类代码必须写在里面,每次保存后都新建一个新的合同明细实体,如果写在外面的话就会报错

java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '0' for key 'PRIMARY'.实体主键id重复了,这时如果你没在方法上加上@Transactional注解,虽然出现报错了,但是数据库还是会执行保存操作,只存入合同明细集合的第一条数据(后面的主键id重复了,不保存),造成数据保存不完整,加了@Transactional后,一但出现错误,就不会执行保存操作(事务的原子性)。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!