这段时间遇到一个 很奇怪的问题。而这个问题,其实一直都困扰着我,只是以前没有怎么去分析,以为是其他问题引起的。可是 这块代码重构时候老是出现问题,而且又不敢随便动,只好慢慢 分析研究了。
问题
情况是这样的, 在spring 事务方法里面, 保存一个 充值对象, 然后将 刚才的新的充值对象 查询出来,修改 里面的某些属性值。 这时候 并没有 执行更新语句,而且执行其他的对象操作更新保存了。 最后呢 ,发现 这个 对象为什么会 字段更新?又没有执行更新方法? 开始一直以为 是其他对象表关联了这个对象表,自动更新了。因为使用的 是 hibernate 。 可是后来分享的时候,发现一点关系没有。。。
代码
代码大概:
// 充值 成功或者失败
if (Objects.equals(result.getCode(), AllinpayConstant.SUCCESS_CODE)) {
// 记录充值前数据
Recharge recharge = new Recharge();
recharge.setReAccount(0d);
// 以元为单位
recharge.setRechargeAmount(Double.valueOf(tranAmt));
recharge.setStatus(Recharge.STATUS_UNDO);
recharge.setUserbasicsinfo(user);
recharge.setRechargetype("1");// 个人网银
recharge.setRechargeWay(Recharge.RECHARGEWAY_SHORTCUTPAY);
recharge.setTime(DateUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
recharge.setOrderNum(reqNo);// 订单号就是 交易批次号
rechargesService.rechargeSave(recharge);
....
// 充值成功后的业务
this.allinPayRechargeAfterDo(result, reqNo, userBank, tranAmtDecimal);
。。。。。
@Transactional(propagation = Propagation.REQUIRES_NEW) // 开启一个新的事务,如果之前有了一个事务,那么挂起
public void allinPayRechargeAfterDo(AllinpayResult result, String reqNo, UserBank userBank,
BigDecimal tranAmtDecimal) {
// 充值成功
Recharge rechargeToSuccess = rechargesService.getRecharge(reqNo);// 查询出来
rechargeToSuccess.setStatus(Recharge.STATUS_SUCCESSE);// 充值成功
rechargeToSuccess.setReAccount(tranAmtDecimal.doubleValue());// 实际充值,以元为单位
// 记录充值成功后相关流水
rechargesService.rechargeReturn(rechargeToSuccess);
。。。。
大概就是这样的情况
分析
其实是这样的, 因为这个方法的 前面的 插入数据的时候, 事务没有提交,而查询的时候 框架可以把自己事务里面未提交的数据给查询出来。 这时候 进行 修改属性值得时候。 事务提交了,就把 这个 充值对象 最新的 给拿出来 存入数据库里面了。 所以不需要 手动去更新了的。就是这样子的简单原因。 可以看到哪怕 更新的时候的 方法 标志使用了 一个新事务 @Transactional(propagation = Propagation.REQUIRES_NEW) 都是不可以避免的。对于 最外层的事务来说 ,都是一样可以控制的。