资金追踪服务中如何让登录用户仅查看自身预算及交易数据?
问题描述
我开发了一款资金追踪服务,需要实现登录用户仅能查看自己的预算、交易等专属数据。我尝试在接口中添加Principal参数,通过用户名获取对应数据,但调用接口后未返回任何数据。
相关代码如下:
Controller层代码
@RestController @RequestMapping("api/v1/budgets") public class BudgetController { private final ModelMapper modelMapper; private final BudgetService budgetService; public BudgetController(ModelMapper modelMapper, BudgetService budgetService) { this.modelMapper = modelMapper; this.budgetService = budgetService; } @GetMapping public ResponseEntity<List<BudgetDTO>> getBudgets(Principal principal){ String loggedInUsername = principal.getName(); List<BudgetDTO> budgetsDto = budgetService.getBudgetsByCreatedBy(loggedInUsername, 5, 5).stream().map(budget -> modelMapper.map(budget, BudgetDTO.class)) .collect(Collectors.toList()); return new ResponseEntity<List<BudgetDTO>>(budgetsDto, HttpStatus.OK); }
Repository与Service层代码
@Repository public interface BudgetRepo extends JpaRepository<Budget, Long> { Page<BudgetDTO> findByUserId(Long userId, Pageable page); } public ArrayList<BudgetDTO> getBudgetsByCreatedBy(String username, int page, int size) { User user = userRepo.getUserByUsername(username); Pageable pageable = PageRequest.of(page, size, Sort.Direction.DESC, "goal"); Page<BudgetDTO> budgets = budgetRepo.findByUserId(user.getId(), pageable); return new ArrayList<BudgetDTO>(budgets.getContent()); }
调用接口后无数据返回,截图如下:
排查与解决方案
1. 修正分页参数逻辑
PageRequest.of(page, size)中的page参数是从0开始计数的,你传入的page=5实际请求的是第6页数据。如果该用户的预算数据不足30条(5页×5条),自然返回空列表。
先测试page=0确认是否能拿到数据:
List<BudgetDTO> budgetsDto = budgetService.getBudgetsByCreatedBy(loggedInUsername, 0, 5)...
2. 修正Repository返回类型
JpaRepository的查询方法默认返回实体类Budget,直接返回Page<BudgetDTO>会因为映射问题导致结果为空。修改Repository方法:
@Repository public interface BudgetRepo extends JpaRepository<Budget, Long> { Page<Budget> findByUserId(Long userId, Pageable page); }
同时更新Service层,在Service中完成实体到DTO的转换:
public ArrayList<BudgetDTO> getBudgetsByCreatedBy(String username, int page, int size) { User user = userRepo.getUserByUsername(username); Pageable pageable = PageRequest.of(page, size, Sort.Direction.DESC, "goal"); Page<Budget> budgets = budgetRepo.findByUserId(user.getId(), pageable); return budgets.stream() .map(budget -> modelMapper.map(budget, BudgetDTO.class)) .collect(Collectors.toCollection(ArrayList::new)); }
3. 验证数据关联关系
检查Budget实体的userId字段是否与数据库中记录一致,直接执行SQL验证:
SELECT * FROM budget WHERE user_id = (SELECT id FROM user WHERE username = '你的测试用户名');
如果查询为空,说明数据插入时未正确关联用户ID,需要修正数据写入逻辑。
4. 确认用户名获取正确性
在Controller层添加日志打印,确认Principal获取的用户名是当前登录用户的正确用户名:
@GetMapping public ResponseEntity<List<BudgetDTO>> getBudgets(Principal principal){ String loggedInUsername = principal.getName(); System.out.println("当前登录用户:" + loggedInUsername); // 后续代码... }
如果用户名不符,需要检查Spring Security的认证配置是否正确。
5. 添加用户查询空值判断
确保userRepo.getUserByUsername(username)能返回有效用户,避免空指针或无效查询:
public ArrayList<BudgetDTO> getBudgetsByCreatedBy(String username, int page, int size) { User user = userRepo.getUserByUsername(username); if(user == null) { return new ArrayList<>(); } // 后续代码... }
内容的提问来源于stack exchange,提问作者doneskk
相关产品推荐
相关产品推荐

