Spring Data JPA 参数陷阱:从 500 错误到完美解决的奇妙之旅 ✨

🚀 Spring Data JPA 参数陷阱:从 500 错误到完美解决的奇妙之旅 🌟

嘿,各位技术冒险家!👋 今天我要带你们走进一场 Spring Data JPA 的"参数迷雾"救援行动------从一个让人抓狂的 500 错误,到最终找到真相并解决的全过程!💪 这篇博客不仅有干货,还有代码、流程图和一点小吐槽,快系好安全带,跟我一起跳进这个技术坑吧!😎


🐞 第一幕:500 错误的"神秘来信"

问题登场!😱

我在开发一个分页查询接口,信心满满地丢了个测试 JSON:

json 复制代码
{
  "field": "",
  "page": 0,
  "size": 10,
  "value": null
}

结果,服务器毫不留情地回了我一个 500 错误:

sql 复制代码
"At least 2 parameter(s) provided but only 1 parameter(s) present in query."

啥?参数不匹配?我直接懵圈了。🤦‍♂️


🔍 第二幕:代码探秘与日志线索

我的代码长啥样?🧐

先看看控制器:

java 复制代码
@PostMapping("/listInviteCodeByPageWithSearch")
public BaseResult listInviteCodeByPageWithSearch(
    @SessionAttribute("adminId") Integer adminId,
    @Valid @RequestBody PageWithSearch pageWithSearch) {
    try {
        Page<InviteCode> inviteCodePage = inviteCodeService.findPaginatedInviteCodeByAdminIdAndSearch(adminId, pageWithSearch);
        return BaseResult.success(inviteCodePage);
    } catch (Exception e) {
        return BaseResult.failure(500, "分页查询失败:" + e.getMessage());
    }
}

再看服务层逻辑:

java 复制代码
public Page<InviteCode> findPaginatedInviteCodeByAdminIdAndSearch(Integer adminId, PageWithSearch pageWithSearch) {
    PageRequest pageRequest = PageRequest.of(pageWithSearch.getPage(), pageWithSearch.getPageSize());
    String field = pageWithSearch.getField();
    String value = pageWithSearch.getValue();

    if (!StringUtils.isEmpty(field) && !StringUtils.isEmpty(value)) {
        return inviteCodeRepository.findPaginatedInviteCodeByAdminIdAndFieldAndValue(adminId, field, value, pageRequest);
    } else {
        return inviteCodeRepository.findByAdminId(adminId, pageRequest);
    }
}

Repository 接口里有个关键方法:

java 复制代码
Page<InviteCode> findByAdminId(Integer adminId, PageRequest pageRequest);

日志说了啥?🕵️‍♂️

我加了日志,输出是这样的:

sql 复制代码
2025-03-18 21:05:15.840 INFO : Calling findByAdminId
param:adminId args:7
param:pageWithSearch args:PageWithSearch@22e239cd
  • 确认调用了 findByAdminId
  • 参数:adminId = 7pageRequest 基于 page=0, size=10
    一切看起来正常,可为啥报错呢?🤨

🔧 第三幕:揪出元凶,解决问题!

真相大白!💡

问题出在 findByAdminId 的签名:

java 复制代码
Page<InviteCode> findByAdminId(Integer adminId, PageRequest pageRequest);
  • Spring Data JPA 期待分页参数是 Pageable,而不是具体的 PageRequest
  • 当我用了 PageRequest,JPA 误以为它是一个查询参数,导致它认为"需要 2 个参数(adminIdpageRequest)",但实际查询只绑定了 adminId,于是报错了!
Mermaid 流程图:错误发生过程

输入 JSON: field='', value=null 服务层: 判断条件不成立 调用 findByAdminId(adminId, pageRequest) JPA 解析: adminId=?1, pageRequest=?2 生成 SQL: WHERE admin_id=?1 错误: 参数数量不匹配

修复方案 🛠️

PageRequest 改成 Pageable,问题迎刃而解:

java 复制代码
Page<InviteCode> findByAdminId(Integer adminId, Pageable pageable);

服务层调用保持不变(PageRequest 兼容 Pageable):

java 复制代码
PageRequest pageRequest = PageRequest.of(pageWithSearch.getPage(), pageWithSearch.getPageSize());
return inviteCodeRepository.findByAdminId(adminId, pageRequest);

再次测试,500 错误消失,数据正常返回!🎉

修复后的流程图

输入 JSON: field='', value=null 服务层: 判断条件不成立 调用 findByAdminId(adminId, pageable) JPA 解析: adminId=?1, pageable=分页参数 生成 SQL: WHERE admin_id=?1 LIMIT 10 OFFSET 0 成功返回分页数据


🌈 第四幕:经验教训与总结

这次我学到了啥?💡

  1. Spring Data JPA 的分页规范 :分页参数必须用 Pageable,别自作主张用 PageRequest
  2. 调试神器:日志 + 流程图,快速定位问题。
  3. 细心点:一个小小的参数类型,就能引发大麻烦。

小建议 🌟

  • 开启 SQL 日志 :看看 JPA 到底生成了啥:

    properties 复制代码
    spring.jpa.show-sql=true
    logging.level.org.hibernate.SQL=DEBUG
  • Specification :动态查询更灵活,比如:

    java 复制代码
    Specification<InviteCode> spec = (root, query, cb) -> cb.equal(root.get("adminId"), adminId);

🎬 尾声

从 500 错误的迷雾到真相大白,这趟旅程让我又爱又恨 Spring Data JPA。希望这篇博客能帮你在开发路上少踩坑!有问题欢迎留言,咱们一起聊技术!✌️

相关推荐
l1t18 分钟前
利用DeepSeek优化SQLite求解数独SQL用于DuckDB
开发语言·数据库·sql·sqlite·duckdb
lcanfly21 分钟前
Mysql作业5
android·数据库·mysql
rit843249926 分钟前
在Ubuntu上配置Nginx实现开机自启功能
数据库·nginx·ubuntu
海绵啵啵呀1 小时前
SQL plus中解决上下键找历史命令的工具--rlwrap命令行工具
数据库·sql
Elastic 中国社区官方博客1 小时前
使用 Mastra 和 Elasticsearch 构建具有语义回忆功能的知识 agent
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
老邓计算机毕设1 小时前
SSM危险品运输车辆信息管理系统b2z1o(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·ssm 框架
MuYiLuck1 小时前
redis持久化与集群
java·数据库·redis
卓码软件测评2 小时前
软件数据库测试:【数据库质量保障:从单元测试到性能优化】
运维·数据库·测试用例·压力测试
LilySesy2 小时前
ABAP+在select的时候,可以A=B A=C B=C这样子JOIN吗?
数据库·sql·ai·excel·sap·abap
升鲜宝供应链及收银系统源代码服务2 小时前
升鲜宝生鲜配送供应链管理系统--- 《多语言商品查询优化方案(Redis + 翻译表 + 模糊匹配)》
java·数据库·redis·bootstrap·供应链系统·生鲜配送·生鲜配送源代码