You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

更新关联Wallet的Transaction时金额始终不变的问题排查

问题分析与解决方案

核心错误点

  • 控制器层覆盖了新提交的数据:你在控制器中接收了表单提交的Transaction对象(包含修改后的新金额15),但紧接着执行了transaction = transactionService.getTransactionById(transactionId);,直接用数据库查询出来的旧数据(金额1)覆盖了新对象,导致后续所有操作都用的是旧值。
  • 服务层重复查询旧数据:Service方法里再次执行transaction = getTransactionById(transactionId);,彻底丢弃了传入的(本应是更新后)的数据,完全没用到页面提交的新金额。
  • 余额计算逻辑错误:就算拿到新金额,当前逻辑是直接加amount,但这是更新操作,应该计算新金额与旧金额的差值,再把差值加到钱包余额里,否则每次调用都会重复累加旧金额。

修正后的代码

控制器层修正

@PostMapping("/updateIncome/{transactionId}")
public String updateIncome(@PathVariable(value = "transactionId") long transactionId, 
                          @Valid Transaction updatedTransaction, 
                          BindingResult result, 
                          Model model) {

    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    UserDetailsImpl user = (UserDetailsImpl) authentication.getPrincipal();
    long userId = user.getId();

    // 先验证新提交的数据,再查询旧数据
    if (result.hasErrors()) {
        model.addAttribute("incomeCategories", IncomeCategories.values());
        return "income_transaction";
    }

    // 从数据库获取旧的交易记录
    Transaction oldTransaction = transactionService.getTransactionById(transactionId);
    // 计算金额差值:新金额 - 旧金额
    double amountDiff = updatedTransaction.getAmount() - oldTransaction.getAmount();
    
    // 更新旧交易的属性为新提交的值
    oldTransaction.setAmount(updatedTransaction.getAmount());
    oldTransaction.setNote(updatedTransaction.getNote());
    oldTransaction.setDate(updatedTransaction.getDate());
    oldTransaction.setIncomeCategories(updatedTransaction.getIncomeCategories());
    // 其他需要更新的属性同理

    // 调用service更新,传入更新后的交易对象和差值
    transactionService.updateIncome(oldTransaction, amountDiff);

    return "redirect:/api/wallet/userWallet/balance/" + userId;
}

服务层修正

@Override
public void updateIncome(Transaction updatedTransaction, double amountDiff) {
    // 更新钱包余额:加上金额差值
    Wallet wallet = updatedTransaction.getWallet();
    wallet.setInitialBalance(wallet.getInitialBalance() + amountDiff);
    // 保存更新后的交易(因为配置了CascadeType.ALL,钱包余额会级联更新)
    this.transactionRepository.save(updatedTransaction);
}

关键说明

  1. 保留新提交的数据:控制器不再覆盖新的Transaction对象,而是先验证,再查询旧数据并将新属性赋值过去,确保新的金额被保留。
  2. 计算金额差值:更新操作需要用新金额减去旧金额得到差值,再调整钱包余额,避免重复累加的问题。
  3. 利用级联更新:因为Wallet和Transaction的关联配置了CascadeType.ALL,保存更新后的Transaction时,关联的Wallet余额会自动同步到数据库。

内容的提问来源于stack exchange,提问作者Frosty Nah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 08:12:03