⚡ Spring JDBC 完整体系 · 第 8 讲 · 查询四象限完备
⚡ Spring JDBC 完整体系 · 第 8 讲 · 查询四象限完备相关开源地址核心框架源码https://gitee.com/gao_zhenzhong/simple-dao系统底座https://gitee.com/gao_zhenzhong/simple-dao-starter代码生成器https://gitee.com/gao_zhenzhong/simple-dao-coder实战案例本集源码https://gitee.com/gao_zhenzhong/simple-dao-demo 前置知识✅ 你只需要会❌ 你完全不需要会的Java 基础 Spring Boot 基本用法Spring 自动配置源码细节第 6-7 讲JdbcTemplate 增删改 命名参数MyBatis / Hibernate 任何知识基础 SQLSELECT、聚合函数连接池调优细节 全套教程总览20 讲从零到架构师篇章涵盖讲次核心目标开篇筑基第 1-3 讲认知梳理建立 Spring JDBC 的底层坐标系API 精讲第 4-7 讲全面掌握 JdbcTemplate 事务体系工具封装第 8-9 讲手搓条件工具 代码生成器从使用者变创造者认知升华第 10 讲模板确定性 vs AI 不确定性建立技术判断力高阶扩展第 11-17 讲多数据源、分库分表、分布式事务底层观测第 18-19 讲SQL 拦截、性能监控、连接池调优终极收尾第 20 讲全链路复盘 手搓持久层框架一、开篇 · 查询的四象限完备前两讲我们分别完成了JdbcTemplate的增删改操作第 6 讲和NamedParameterJdbcTemplate的命名参数第 7 讲。这一讲回归查询——SELECT 语句的结果形态分析。无论 SQL 写得多复杂——多表 JOIN、子查询、聚合函数、窗口函数——最终落到 Java 代码里查询结果只有四种形态。这就是所谓的四象限完备。具体是哪四种我们用一张图说清楚单列多列单行单行单列单行多列多行多行单列多行多列单行单列聚合函数COUNT、MAX、SUM等或唯一键查单个字段单行多列根据主键 ID 查询完整实体多行单列查某一列的所有值如所有用户名称列表多行多列最常规的列表查询返回多条完整记录这一讲的目标很明确四个方法四种形态覆盖所有查询场景没有遗漏没有重叠。二、项目结构与前置代码2.1 依赖与配置pom.xml沿用spring-boot-starter-jdbc H2 Lombok 的标准组合application.yml配置数据源并自动执行schema.sqllogback-spring.xml开启JdbcTemplate的 DEBUG 日志。细节同第 5-7 讲此处不再赘述。2.2 schema.sql · 建表与初始数据DROPTABLEIFEXISTSsys_user;CREATETABLEsys_user(user_idBIGINTAUTO_INCREMENTPRIMARYKEYCOMMENT主键,user_nameVARCHAR(50)COMMENT姓名,birthdayDATECOMMENT生日,genderTINYINTCOMMENT性别,ageINTCOMMENT年龄);INSERTINTOsys_user(user_name,birthday,gender,age)VALUES(郭靖,2018-07-13,1,25),(洪七公,2018-07-13,1,30),(王重阳,2018-07-13,1,40),(周伯通,2018-07-13,1,35),(李莫愁,2018-07-13,0,28);2.3 User.java · 实体类DataBuilderAllArgsConstructorNoArgsConstructorpublicclassUser{privateLonguserId;/* 主键 */privateStringuserName;/* 姓名 */privateLocalDatebirthday;/* 生日 */privateBytegender;/* 性别 */privateIntegerage;/* 年龄 */}三、demo01 · 单行多列 · findById场景根据主键 ID 查询单条记录返回完整实体对象。RepositorypublicclassUserDao{AutowiredprivateJdbcTemplatejdbc;publicvoiddemo01(){StringsqlSELECT user_id, user_name, birthday, gender, age FROM sys_user WHERE user_id ?;Useruserjdbc.queryForObject(sql,newBeanPropertyRowMapper(User.class),1L);log.info(user{},user);}}核心 API 拆解要素说明queryForObject期望结果集恰好一行的方法。多于一行会抛出IncorrectResultSizeDataAccessExceptionBeanPropertyRowMapper自动映射下划线字段user_id到驼峰属性userId第三个参数1L?占位符的实际参数值queryForObject与query的区别在于queryForObject底层调用query获取List然后断言list.size() 1若为 0 抛出EmptyResultDataAccessException若大于 1 抛出IncorrectResultSizeDataAccessException。因此只有确信结果集只有一行时如按主键查询才使用queryForObject。[INFO] userUser(userId1, userName郭靖, birthday2018-07-13, gender1, age25)四、demo02 · 单行单列 · 聚合统计场景聚合函数——COUNT、SUM、AVG、MAX、MIN返回单个值。publicvoiddemo02(){StringsqlSELECT COUNT(age) FROM sys_user WHERE user_id ?;Longcountjdbc.queryForObject(sql,Long.class,0L);log.info(count{},count);}核心 API 拆解要素说明queryForObject(sql, ClassT, args...)直接返回目标类型的单值无需RowMapperLong.class返回类型。支持Integer、Long、String、Date等基础类型/包装类型0L?占位符参数此处代表查询user_id 0的所有记录COUNT(age)会忽略age为NULL的行。如果表中数据为空COUNT返回0不会触发EmptyResultDataAccessException。但其他聚合函数如MAX、MIN在空表上会返回NULL映射为Long时需注意 NPE 问题建议使用Long.class而非long.class。[INFO] count5五、demo03 · 多行单列 · 取某一列场景只需要某一列的数据用于校验、去重、构造集合等场景。publicvoiddemo03(){StringsqlSELECT user_name FROM sys_user WHERE user_id ?;ListStringnamesjdbc.query(sql,newSingleColumnRowMapper(String.class),0L);log.info(names{},names);}核心 API 拆解要素说明query返回ListT零行时返回空列表不抛异常SingleColumnRowMapper专门处理单列多行结果集指定列的目标类型String.class列值映射到的目标类型SingleColumnRowMapper的底层逻辑对ResultSet的每一行只取第一列column index 1然后通过ConversionService或直接类型转换将 JDBC 类型映射为指定的 Java 类型。对于字符串列直接调用rs.getString(1)对于数值列调用rs.getObject(1)后转换为目标类型。零行时返回空列表与queryForObject不同——后者会抛异常。[INFO] names[郭靖, 洪七公, 王重阳, 周伯通, 李莫愁]六、demo04 · 多行多列 · 常规列表场景最常规的列表查询返回多条完整记录。PostConstructpublicvoiddemo04(){StringsqlSELECT user_id, user_name, birthday, gender, age FROM sys_user WHERE user_id ?;ListUserusersjdbc.query(sql,newBeanPropertyRowMapper(User.class),-1L);users.forEach(u-log.info(user{},u));}核心 API 拆解要素说明PostConstructBean 初始化后自动执行此处用于演示启动时打印数据query返回ListUser零行时返回空列表BeanPropertyRowMapper自动完成下划线转驼峰映射-1L参数值此处用于查询user_id -1即全部记录为什么用PostConstruct本讲的所有 demo 都是通过这个注解在 Spring 容器启动后自动执行的。这是一种演示技巧让你无需编写 Controller 或手动调用启动应用就能看到四种查询形态的输出结果。实际业务中查询方法通常由 Service 层调用而非在 DAO 中用PostConstruct驱动。[INFO] userUser(userId1, userName郭靖, birthday2018-07-13, gender1, age25) [INFO] userUser(userId2, userName洪七公, birthday2018-07-13, gender1, age30) [INFO] userUser(userId3, userName王重阳, birthday2018-07-13, gender1, age40) [INFO] userUser(userId4, userName周伯通, birthday2018-07-13, gender1, age35) [INFO] userUser(userId5, userName李莫愁, birthday2018-07-13, gender0, age28)七、四种查询 API 汇总象限APIRowMapper返回值零行时行为单行多列queryForObjectBeanPropertyRowMapper单个实体对象抛EmptyResultDataAccessException单行单列queryForObject无需 RowMapper传ClassT单个值Long/String等抛EmptyResultDataAccessException多行单列querySingleColumnRowMapperListT返回空列表多行多列queryBeanPropertyRowMapperListEntity返回空列表关键区别queryForObjectvsquery行为queryForObjectquery零行抛EmptyResultDataAccessException返回空列表一行返回该行返回包含一个元素的列表多行抛IncorrectResultSizeDataAccessException返回包含多个元素的列表⚠️实践中需要注意queryForObject并不能保证最多一行它只是期待一行。如果 SQL 条件写错导致返回多行比如按非唯一字段查询应用会直接抛出异常。因此queryForObject只适用于按主键或唯一约束查询的场景。对于其他单行查询优先用query 手动判断list.isEmpty()更加健壮。八、本讲核心总结核心要点说明四象限完备单行单列、单行多列、多行单列、多行多列覆盖所有查询场景queryForObjectBeanPropertyRowMapper单行多列 → 单个实体对象queryForObjectClassT单行单列 → 单个值聚合函数querySingleColumnRowMapper多行单列 →ListT某一列queryBeanPropertyRowMapper多行多列 →ListEntity最常规零行处理差异queryForObject抛异常query返回空列表九、下集预告第 9 讲将进入BaseCondition 条件封装——手搓条件类让动态 SQL 从散装if收敛为可复用的语义单元原生 JDBC 拼接动态 SQL 的痛点大量 if 判空冗余代码 BaseCondition 设计思路条件收集 参数收集 等值、区间、前后模糊、IN 条件的 API 设计 参数自动收集与 WHERE 语句生成

相关新闻

App开发全流程解析:从构思到上线的实战指南

App开发全流程解析:从构思到上线的实战指南

1. 项目概述:一个App的诞生之旅聊到手机App开发,很多人第一反应是写代码。但作为一个在这个行业里摸爬滚打了十多年的老手,我必须告诉你,写代码只是整个漫长旅程中的一段路,而且往往不是最复杂的那段。一个App从脑子里…

2026/8/6 4:24:44 阅读更多 →
2025年CS2启动项终极配置指南:从引擎原理到实战优化

2025年CS2启动项终极配置指南:从引擎原理到实战优化

1. 项目概述:为什么CS2启动项依然重要?如果你是从CS:GO时代一路玩过来的老玩家,可能会觉得启动项这东西有点“过时”了。毕竟游戏内设置越来越丰富,很多以前需要靠启动项调整的参数,现在都能在游戏里直接点选了。但实际…

2026/8/6 4:24:44 阅读更多 →
用Postman深入理解CORS:从HTTP报文视角剖析跨域请求机制

用Postman深入理解CORS:从HTTP报文视角剖析跨域请求机制

1. 项目概述:为什么要在Postman里折腾跨域请求?如果你是一名前端开发者,或者经常和API打交道,那么“跨域请求”这个词对你来说一定不陌生。它就像一道无形的墙,浏览器出于安全考虑,默认禁止了不同源&#x…

2026/8/6 4:24:44 阅读更多 →

最新新闻

【云原生实战】K8s 集群高可用与中间件灾备平台全流程实践

【云原生实战】K8s 集群高可用与中间件灾备平台全流程实践

📌 创作灵感 记录云原生运维项目完整实践复盘整理 K8s 高可用、中间件灾备、故障切换技术笔记将个人原创实操项目文档搬运发布于此 📖 目录 一、项目概述二、整体架构设计三、环境规划四、入口层高可用(HAProxy Keepalived) 4.1…

2026/8/6 17:06:15 阅读更多 →
Shopify 店长,别再被“订单去哪了”困住——用 BestTrack 轻松追踪物流

Shopify 店长,别再被“订单去哪了”困住——用 BestTrack 轻松追踪物流

别再猜订单去哪了,让每一次物流查询都创造价值。 BestTrack 帮你把所有包裹动态集中到一个看板,并为顾客提供品牌化的自助查询体验。 万单物流,一屏掌控:集中管理海量订单,物流状态一目了然。顾客自助查询&#xff0…

2026/8/6 17:06:15 阅读更多 →
天气丹代加工源头工厂:韩方发酵霜的车间公差,才是老板该盯的死角

天气丹代加工源头工厂:韩方发酵霜的车间公差,才是老板该盯的死角

做私域的老板一上来就问“某韩系头部品牌经典发酵霜 / 韩系高端发酵抗老霜你们能不能做”,我一般不急着回话,先反问一句:你要的是瓶身上那排韩文,还是打开盖子那股淡药草发酵香?这一个问题,能筛掉一半只会比…

2026/8/6 17:06:15 阅读更多 →
别被“大牌同款料体”忽悠了!口红一件代发的水深在哪?车间主任跟你唠透

别被“大牌同款料体”忽悠了!口红一件代发的水深在哪?车间主任跟你唠透

各位老板,我是常年蹲在口红灌装车间里跟色粉、蜡基打交道的老师傅。最近好多做私域、开实体店的老板来找我,开口第一句就是“有没有大牌同款口红料体?能一件代发那种”。我先把话撂这儿:所谓“大牌同款”,在化工厂里就…

2026/8/6 17:06:15 阅读更多 →
大牌同款OEM代工厂:进货验货与源头对接的车间内参

大牌同款OEM代工厂:进货验货与源头对接的车间内参

拿着大牌正装图片跑到广州、上海一堆代工厂问“能不能做”,十个业务员九个说能。但真正能把料体肤感、防腐体系、包材公差全部拉到同一水平线的工厂,掰着手指头数得过来。▼ 源头车间质检备案与合作授权说明 ▼配方框架决定同源深度入行这么多年&#xf…

2026/8/6 17:06:14 阅读更多 →
AI-Shoujo HF Patch终极指南:5步快速解锁完整游戏体验

AI-Shoujo HF Patch终极指南:5步快速解锁完整游戏体验

AI-Shoujo HF Patch终极指南:5步快速解锁完整游戏体验 【免费下载链接】AI-HF_Patch Automatically translate, uncensor and update AI-Shoujo! 项目地址: https://gitcode.com/gh_mirrors/ai/AI-HF_Patch AI-Shoujo HF Patch是一款专为AI-Shoujo游戏设计的…

2026/8/6 17:05:14 阅读更多 →

日新闻

深入解析LimboAI C++内核:架构设计与性能优化实战

深入解析LimboAI C++内核:架构设计与性能优化实战

1. 项目概述:为什么我们需要深入LimboAI的C内核?如果你是一名使用Godot引擎的游戏开发者,尤其是对AI行为逻辑有较高要求的项目,那么LimboAI这个名字你大概率不会陌生。它作为Godot 4生态中一个备受瞩目的行为树与状态机插件&#…

2026/8/6 0:00:06 阅读更多 →
Unity 2D游戏敌人AI系统:基于PlayMaker状态机与2D Toolkit的实战开发

Unity 2D游戏敌人AI系统:基于PlayMaker状态机与2D Toolkit的实战开发

1. 项目概述与核心思路大家好,我是老张,一个在游戏开发一线摸爬滚打了十多年的老码农。今天咱们接着聊《空洞骑士》风格2D动作游戏的Demo制作。上一期我们搭好了基础框架,处理了角色移动和碰撞,这一期,我们要让游戏世界…

2026/8/6 0:00:06 阅读更多 →
被动防火门市场前景发展趋势

被动防火门市场前景发展趋势

被动防火门依靠材质结构、密闭构造阻隔烟火蔓延,无需电控启动,是建筑被动消防系统核心构件,行业依托新规管控、城市更新、工业安全升级迎来稳定扩容,整体朝着合规化、专项化、低碳化、智能化方向发展。现阶段 GB12955‑2024 新版国…

2026/8/6 0:00:06 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/5 15:00:43 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/5 13:13:56 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/5 10:20:36 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/5 23:28:39 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/5 21:00:14 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/5 23:46:51 阅读更多 →