JAVA-JDBC事务基础概念及测试方法

对java-JDBC事务的基本理解

事务:原子操作单元,比如从数据库角度,就是一组SQL指令,要么全部执行成功,若其中一条SQL执行失败,则自动撤销(回滚)已经执行成功的SQL,总结来说是:要么全部执行成功,要么回滚不执行。

数据库事务的实现是通过java程序,所以数据库事务也可以称之为java事务。

PS:Java中使用事务处理,首先要求数据库支持事务。如使用MySQL的事务功能,就要求MySQL的表类型为Innodb才支持事务。否则,在Java程序中做了commit或rollback,但在数据库中根本不能生效。

事务的特性

原子性:原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚;

一致性:事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态;

隔离性:隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离;

持久性:持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

为什么需要事务?

事务是为解决数据安全操作及正确性提出的,事务控制实际上就是控制数据的安全访问,保证数据的正确性。

事务实现的简单事实例

退款场景的模拟,退款操作一般需要完成两张表的状态更新,订单表和退款流水表,流程一般是发起退款时,订单表状态更新为退款处理中,退款流水表入库一条数据,然后,程序进行其他的校验操作,比如风控,若风控校验未通过,那么退款将失败,此时退款表需要将状态更新为失败状态,订单表因退款失败,则需要回滚为支付成功未退款的状态;

那么,事务的作用就明显的展现出来了,如果不使用事务,会出现两张表状态不同步的情况,再次发起退款时会导致失败,事务的处理,保证了两张表状态的同步性,数据的一致性。

/**
  * 退款,风控校验未通过,流水表状态U更新为F,订单表R1回滚为S,事务处理
*/

    @Transactional(rollbackFor = Exception.class)
    public void updatePayOrdInfoAndRefund(PayOrderInfo payOrderInfo, RefundOrderInfo refundOrderInfo, TradeRiskCtrlResp tradeRiskCtrlResp) {
        int result = payOrderInfoMapper.updateRiskResult(tradeRiskCtrlResp.getMsgInf(), tradeRiskCtrlResp.getMsgCd(), PayOrderInfoStsEnum.R1.getStatus(), PayOrderInfoStsEnum.S.getStatus(), payOrderInfo.getOrdNo());
        if (result == 0) {
            throw new UnexpectedRollbackException("PayOrderInfo更新表异常");
        }
        result = refundOrderInfoMapper.updateRiskResult(tradeRiskCtrlResp.getMsgInf(), tradeRiskCtrlResp.getMsgCd(), RefundOrderInfoStsEnum.U.getStatus(), RefundOrderInfoStsEnum.F.getStatus(), refundOrderInfo.getRfdOrdNo());
        if (result == 0) {
            throw new UnexpectedRollbackException("refundOrderInfo表入库异常");
        }
    }

对于JDBC事务的测试方法

1、通过设置延时并更改数据进行测试

在两张表数据进行更新操作的中间增加延时等待时间,在等待时,手动update第二张表的数据为异常,然后关注结果,第一张表的状态是否正确回滚。

2、通过debug模式进行测试

启动服务,开启debug模式,在第二张表进行更新操作前,手动update第二张表的数据为异常,然后关注结果,第一张表的状态是否正确回滚。

3、单测

测试类代码中模拟操作第二张表时抛出异常,关注事务对第一张表的处理。

 

 

 

你可能感兴趣的:(测试)