java事务异常 try catch throw new BusinessException

今天找了一个之前小伙伴写的bug代码,大致内容如下:

try {
                System.out.println("调用接口处理开始");
                feePersonAdd=this.feePerson(null, null, prpSverifyDetail.getVerifyType(), userCodeStr);//主要是保存报文操作
                System.out.println("调用口处理结束");
            } catch (Exception e) {
                e.printStackTrace();
            }
            if(!feePersonAdd){
                throw new BusinessException("任务预处理时发生异常。调用接口失败。", false);
            }

可以看到在进行一系列操作之后,如果出现异常,则最后执行 throw new  BusinessException("任务预处理时发生异常。调用接口失败。", false); 这就导致会将失败的报文丢失掉,最终结果是,如果调用成功,则报文可以正常保存,如果调用失败,则报文丢失,为什么为造成这样的现象呢?

那是因为在写代码的时候没有考虑到Spring的事物机制,默认spring事务只在发生未被捕获的 runtimeexcetpion时才回滚,而BusinessException类是继承了RuntimeException 。

如果使用声明式事务管理,@Transactional,默认情况下所有的RuntimeException会触发回滚,所有的checked Exception不会触发回滚,可以通过rollback-for和no-rollback-for来调整配置,如果单单只是 catch异常,没有抛出,则异常没办法到事务管理器中,不会触发回滚操作。简单点可以理解为:使用 throw  RuntimeException  则事务会回滚。

针对以上代码,解决方案为重新申明一个session事务,用来单独提交保存报文这个事务:

Session session = super.getHibernateTemplate().getSessionFactory().openSession();
     Transaction transaction = session.beginTransaction();
     session.saveOrUpdate(xmlMessage);
     transaction.commit();
     session.close();

在开发过程中常见的RuntimeException类型的异常主要有以下几种:
 ArithmeticException:数学计算异常。
 NullPointerException:空指针异常。
 NegativeArraySizeException:负数组长度异常。
 ArrayOutOfBoundsException:数组索引越界异常。
 ClassNotFoundException:类文件未找到异常。
 ClassCastException:类型强制转换异常。
 SecurityException:违背安全原则异常。
IllegalArgumentException- 传递非法参数异常
ArrayStoreException - 向数组中存放与声明类型不兼容对象异常
IndexOutOfBoundsException - 下标越界异常
NumberFormatException - 数字格式异常
UnsupportedOperationException - 不支持的操作异常


其他非RuntimeException类型的常见异常主要有以下几种:
NoSuchMethodException:方法未找到异常。
 IOException:输入输出异常。
EOFException:文件已结束异常。
FileNotFoundException:文件未找到异常。
NumberFormatException:字符串转换为数字异常。
SQLException:操作数据库异常

try { if (StringUtils.isBlank(AccessTokenInfoRequestDTO.getAccessToken())) { throw new BusinessException(ResponseCodeEnum.ACCESSTOKEN_ILLEGAL.getCode(), ResponseCodeEnum.ACCESSTOKEN_ILLEGAL.getMessage()); } else { TokenInfoDTO tokenInfoDTO = this.getTokenInfo(AccessTokenInfoRequestDTO.getAccessToken()); String accountId = tokenInfoDTO.getUserId(); String deviceToken = tokenInfoDTO.getDeviceToken(); String accToken = RedisCacheUtil.getStringForPrefix(accountId, new RedisTokenKeyEnum[]{RedisTokenKeyEnum.APP_USER_ACCOUNT}); if (StringUtils.isEmpty(accToken)) { throw new BusinessException(ResponseCodeEnum.ACCESS_TOKEN_LOSE.getCode(), ResponseCodeEnum.ACCESS_TOKEN_LOSE.getMessage()); } else if (!AccessTokenInfoRequestDTO.getAccessToken().equals(accToken)) { throw new BusinessException(ResponseCodeEnum.ACCESS_TOKEN_COVER.getCode(), ResponseCodeEnum.ACCESS_TOKEN_COVER.getMessage()); } else if (!ContextUtils.getAppRequestHeaderDTO().getDeviceToken().equals(deviceToken)) { throw new BusinessException(ResponseCodeEnum.ACCESS_TOKEN_COVER.getCode(), ResponseCodeEnum.ACCESS_TOKEN_COVER.getMessage()); } } } catch (BusinessException businessException) { LogUtil.boErrorLog("校验用户token失败:" + businessException.getMessage()); verifyAccessTokenResponseDTO = VerifyAccessTokenResponseDTO.builder().verifyFlag(false).errorDescription(businessException.getMessage()).build(); } catch (Exception exception) { LogUtil.boErrorLog("校验用户token异常:" + exception.getMessage()); verifyAccessTokenResponseDTO = VerifyAccessTokenResponseDTO.builder().verifyFlag(false).errorDescription(ResponseCodeEnum.ACCESSTOKEN_ILLEGAL.getMessage()).build(); }是啥意思
06-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心寒丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值