更新关联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); }
关键说明
- 保留新提交的数据:控制器不再覆盖新的
Transaction对象,而是先验证,再查询旧数据并将新属性赋值过去,确保新的金额被保留。 - 计算金额差值:更新操作需要用新金额减去旧金额得到差值,再调整钱包余额,避免重复累加的问题。
- 利用级联更新:因为
Wallet和Transaction的关联配置了CascadeType.ALL,保存更新后的Transaction时,关联的Wallet余额会自动同步到数据库。
内容的提问来源于stack exchange,提问作者Frosty Nah
相关产品推荐
相关产品推荐

