mashining1988111 2022-02-28 17:24 采纳率: 0%
浏览 32

@Transactional 注解在开发环境好使,在测试环境和正式环境没有回滚,查了半天不知道为啥?

前提
本地环境为:windows 10,
正式环境和测试环境均为:linux
数据库为mysql,测试环境和开发环境用的同一个数据库,区别是测试环境用的内网ip,开发环境是用的外网id
java代码,使用的spring-boot框架,

2018年写的老代码了,今天突然出了问题,问题是,@Transactional注解没有回滚,问题描述如下:
Controller调用Service的A方法(A方法有@Transactional注解),
A方法调用同一个Service的B方法(B方法有@Transactional注解),
B方法抛出异常(该异常继承RuntimeException类)
然后A方法的事务没有回滚。

然后我在本地运行代码发现:本地环境正常,事务可以回滚

然后我把上面的代码修改了一下,直接在Service方法的A方法中抛出异常,测试环境仍然没有回滚(本地可以回滚)。

一模一样的代码,在本地可以,在测试环境不行,想问这和运行环境有关系吗?
下面是代码

Controller代码
@RestController
public class UserWithdrawController  {
    @PutMapping("/v1/user-withdraw/audit")
    public boolean auditUserWithdraw(@RequestBody UserWithdrawDeposit uwd,
            @RequestParam("loginUserId") Integer loginUserId) {
        boolean result = withdrawService.auditUserWithdraw(uwd, loginUserId);
        return result;
    }
}

Service代码
@Service
@Slf4j
public class UserWithdrawService {
//  此为A方法
@Transactional
    public boolean auditUserWithdraw(UserWithdrawDeposit uwd, Integer loginUserId) {
        // 判断必填项
        if (StringUtils.isBlank(uwd.getId()) || loginUserId == null) {
            throw new OSWNException(GlobalError.PARAMETERS_IS_EMPTY);
        }
        if (uwd.getAuditStatus() == Constants.USER_WITHDRAW_AUDIT_STATUS_UNPASS.getCode()
                && StringUtils.isBlank(uwd.getReason())) {
            throw new OSWNException(GlobalError.PARAMETERS_IS_EMPTY);
        }

        // 检查申请数据,查询数据库中的退款申请,判断是否为待审核状态,如果不是待审核,提示错误
        UserWithdrawDeposit dbUwd = withdrawMapper.getUserWithdrawById(uwd.getId());
        if (dbUwd == null || dbUwd.getAuditStatus() != Constants.USER_WITHDRAW_AUDIT_STATUS_UNAUDIT.getCode()) {
            throw new OSWNException(GlobalError.PARAMETERS_INVALID);
        }

        // 修改提现申请数据
        uwd.setAuditorId(loginUserId);
        // 查询管理员的账号
        String account = sysUsersMapper.getAccountByUserId(loginUserId);
        uwd.setAuditorName(account);
        Date date = new Date();
        uwd.setAuditTime(date);
        // 修改
        int num = withdrawMapper.auditUserWithdraw(uwd);
        if (num == 0) {
            throw new OSWNException(GlobalError.OPERATION_FAILURE);
        }
        if (num != 0) {// 次判断是为了测试事务写的,此处必报错,
            throw new OSWNException(GlobalError.OPERATION_FAILURE);
        }
        if (uwd.getAuditStatus() == Constants.USER_WITHDRAW_AUDIT_STATUS_PASS.getCode()) {
            // 审核通过,创建订单信息,发送转账请求 ----**这里调用B方法**
            agreeUserWithdraw(dbUwd, loginUserId);
        
        } else if (uwd.getAuditStatus() == Constants.USER_WITHDRAW_AUDIT_STATUS_UNPASS.getCode()) {
            // 审核不通过,返还金额,创建退还提现的订单,创建退还提现和手续费2个流水
            refuseUserWithdraw(dbUwd, loginUserId);

        } else {
            throw new OSWNException(GlobalError.PARAMETERS_INVALID);
        }
    }


//B方法
    /**
     * 同意提现申请
     * 
     * @param uwd
     *            申请信息
     * @param loginUserId
     *            登录用户id
     * @return boolean
     */
    @Transactional
    public boolean agreeUserWithdraw(UserWithdrawDeposit uwd, Integer loginUserId) {
        // 判断用户钱包是否被冻结
        UserWallet userWallet = userWalletMapper.getUserWalletByUserId(uwd.getUserId());
        if (userWallet.getStatus() == Constants.USER_WALLET_STATUS_FROZEN.getCode()) {
            throw new OSWNException(GlobalError.USER_WALLET_IS_FROZEN);
        }
        // 判断用户是否绑定支付账号
        UserPayAccount account = userWalletMapper.getUserAlipayAccount(uwd.getUserId());
        if (account == null) {
            throw new OSWNException(GlobalError.USER_PAY_ACCOUNT_NOT_EXISTS);
        }
        // 查询订单,根据订单进行支付宝转账,返回支付宝支付号
        Order order = orderMapper.getOrderByBusiId(uwd.getId(), Constants.ORDER_BUSI_TYPE_WITHDRAW.getCode());
        if (order == null) {
            throw new OSWNException(GlobalError.ORDER_NOT_EXSIT);
        }
        // 发起支付宝转账
        String alipayOrderId = "";
        // 把转账金额由分换成元
        String totalAmountY = AmountUtils.changeF2Y(order.getTotalAmount());
        AlipayDto alipayDto = new AlipayDto();
        alipayDto.setAmount(totalAmountY);
        alipayDto.setOrderId(order.getId());
        alipayDto.setPayeeAccount(account.getAccount());
        alipayDto.setRemark(order.getDescription());
        alipayDto.setRealName(account.getName());
        try {
            alipayOrderId = alipayService.fundTransToaccountTransfer(alipayDto);
        } catch (AlipayApiException e) {
            throw new OSWNException(GlobalError.OPERATION_FAILURE);
        }
        // 把支付宝支付号回写到流水表
        if (StringUtils.isBlank(alipayOrderId)) {//  走到这段代码抛的异常
            throw new OSWNException(GlobalError.OPERATION_FAILURE);
        }
    }

/**
 * 自定义异常
 *
 * @author HuangTao
 */
public class OSWNException extends RuntimeException {
}
}
  • 写回答

1条回答 默认 最新

报告相同问题?

问题事件

  • 创建了问题 2月28日

悬赏问题

  • ¥15 更换了一个新的win10系统,再下载VS时碰到的问题,是C++组件的?
  • ¥15 关于罗技鼠标宏lua文件的问题
  • ¥15 halcon ocr mlp 识别问题
  • ¥15 已知曲线满足正余弦函数,根据其峰值,还原出整条曲线
  • ¥20 无法创建新的堆栈防护界面
  • ¥15 sessionStorage在vue中的用法
  • ¥15 wordpress更换域名后用户图片头像不显示
  • ¥15 如何在ubunto上安装CEF (Chromium Embedded Framework),并且基于qt实现打开一个web
  • ¥30 AD9854 为什么输出波形幅度受限,AI机器人勿扰
  • ¥15 如何在ubunto上安装CEF (Chromium Embedded Framework