Spring Boot中如何用Transaction数据填充TransactionGroup的列表
问题修复:Spring Boot按日期分组展示交易页面为空
问题概述
我的Spring Boot应用中有Transaction表,需要按日期分组展示交易:仅显示有交易的日期,当日多条交易全部展示,无交易日期跳过。为此创建了TransactionGroup实体(包含LocalDate date和List<Transaction> transactions),但Thymeleaf页面展示为空。排查后确认问题出在:
- 保存交易的Controller中调用的
transactionGroup.setTransactions是空实现,且逻辑冗余 - 展示交易的Controller仅实例化
TransactionGroup,未从数据库获取交易并按日期分组 - Thymeleaf模板存在变量引用错误
相关代码问题分析
1. TransactionGroup实体方法错误
当前setTransactions方法参数设计不合理且为空实现,完全无法填充交易列表:
// 错误的方法 public void setTransactions(String walletName, Double amount, LocalDate date, String note, ExpenseCategories expenseCategories, IncomeCategories incomeCategories) { }
2. 保存交易Controller冗余代码
保存交易时不需要操作TransactionGroup,因为分组逻辑应该在查询阶段处理,而非保存阶段。
3. 展示交易Controller未实现分组逻辑
仅实例化空的TransactionGroup,未查询用户交易并按日期分组,且findDistinctIdByUserId无法获取完整交易数据。
4. Thymeleaf模板变量错误
循环交易时误用${transactions.amount}(循环变量是transaction,应为${transaction.amount});外层循环变量名应为列表类型(比如transactionGroups),而非单个transactionGroup。
修复步骤
步骤1:修正TransactionGroup实体
改为标准的getter/setter,添加构造方法方便分组时创建实例:
import java.time.LocalDate; import java.util.ArrayList; import java.util.List; public class TransactionGroup { private LocalDate date; private List<Transaction> transactions; // 空构造 public TransactionGroup() {} // 带日期的构造,初始化交易列表 public TransactionGroup(LocalDate date) { this.date = date; this.transactions = new ArrayList<>(); } // 标准getter/setter public LocalDate getDate() { return date; } public void setDate(LocalDate date) { this.date = date; } public List<Transaction> getTransactions() { return transactions; } public void setTransactions(List<Transaction> transactions) { this.transactions = transactions; } // 新增添加单个交易的方法 public void addTransaction(Transaction transaction) { this.transactions.add(transaction); } }
步骤2:清理保存交易的Controller代码
删除无关的TransactionGroup逻辑,专注保存交易:
@PostMapping("/saveIncome/{walletId}") public String saveIncome(@PathVariable(value = "walletId") long walletId, @Valid Transaction transaction, BindingResult result, Model model) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); UserDetailsImpl user = (UserDetailsImpl) authentication.getPrincipal(); long userId = user.getId(); Wallet wallet = walletService.getWalletById(walletId); transaction.setWallet(wallet); transaction.setUserId(userId); transaction.setWalletName(wallet.getWalletName()); // 移除TransactionGroup相关代码 transactionService.saveIncome(transaction, walletId, userId); return "redirect:/api/wallet/userWallet/balance/" + userId; }
步骤3:修改展示交易的Controller,实现按日期分组
查询用户所有交易,按日期分组生成List<TransactionGroup>:
import java.util.List; import java.util.Map; import java.util.stream.Collectors; @GetMapping("/userTransactions/{user_id}") public String getUserTransactions(@PathVariable("user_id") long user_id, Model model) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); UserDetailsImpl user = (UserDetailsImpl) authentication.getPrincipal(); long userId = user.getId(); // 1. 查询用户所有交易(需确保transactionService有此方法,若没有则添加) List<Transaction> userTransactions = transactionService.findByUserId(user_id); // 2. 按交易日期分组 Map<LocalDate, List<Transaction>> groupedByDate = userTransactions.stream() .collect(Collectors.groupingBy(Transaction::getDate)); // 3. 转换为TransactionGroup列表 List<TransactionGroup> transactionGroups = groupedByDate.entrySet().stream() .map(entry -> { TransactionGroup group = new TransactionGroup(entry.getKey()); group.setTransactions(entry.getValue()); return group; }) .collect(Collectors.toList()); // 4. 将分组后的列表放入Model model.addAttribute("transactionGroups", transactionGroups); model.addAttribute("userId", userId); return "transactions"; }
注意:需确保
transactionService有findByUserId(long userId)方法,用于查询用户所有交易记录。
步骤4:修正Thymeleaf模板代码
修正循环变量名和交易属性引用:
<!-- 外层循环遍历分组列表 --> <div th:each="group : ${transactionGroups}"> <h1 th:text="${group.date}" /> <!-- 内层循环遍历当日交易 --> <div th:each="transaction : ${group.transactions}"> <h2>Amount: <span th:text="${transaction.amount}"></span></h2><br> <h2>Note: <span th:text="${transaction.note}"></span></h2><br> <h2>Wallet name: <span th:text="${transaction.walletName}"></span></h2><br> <h2>Expense Category: <span th:text="${transaction.expenseCategories}"></span></h2><br> <h2>IncomeCategory: <span th:text="${transaction.incomeCategories}"></span></h2> </div> </div>
内容的提问来源于stack exchange,提问作者Frosty Nah
相关产品推荐
相关产品推荐

