⚡ Spring JDBC 完整体系 · 第 3 讲 · Spring JDBC 最小案例相关开源地址核心框架源码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 基础类、接口、注解、泛型MyBatis / Hibernate 任何知识基础 SQLSELECT、INSERT、WHERE连接池原理、事务隔离级别第 2 讲Spring 容器IoC DIXML 配置、Spring Boot 自动配置 全套教程总览20 讲从零到架构师篇章涵盖讲次核心目标开篇筑基第 1-3 讲认知梳理建立 Spring JDBC 的底层坐标系API 精讲第 4-7 讲全面掌握 JdbcTemplate 事务体系工具封装第 8-9 讲手搓条件工具 代码生成器从“使用者”变“创造者”认知升华第 10 讲模板确定性 vs AI 不确定性建立技术判断力高阶扩展第 11-17 讲多数据源、分库分表、分布式事务底层观测第 18-19 讲SQL 拦截、性能监控、连接池调优终极收尾第 20 讲全链路复盘 手搓持久层框架一、开篇 · 告别裸 JDBC 的繁琐第 2 讲已经建立了 Spring 容器的认知——本质上就是一个 Map。这一讲正式进入Spring JDBC将DataSource和JdbcTemplate注册进容器开始用 Spring 方式操作数据库。对比裸 JDBC第 1 讲和 Spring JDBC本讲对比项裸 JDBCSpring JDBC连接管理手动DriverManager.getConnection()JdbcTemplate自动管理Statement 创建手动conn.createStatement()JdbcTemplate自动创建结果集遍历手动while(rs.next())rs.getString()BeanPropertyRowMapper一行搞定资源关闭手动逆序关闭JdbcTemplate自动关闭SQL 注入风险字符串拼接风险高预编译占位符?根治代码量30 行2-3 行二、极简依赖 · spring-context spring-jdbc 双核驱动组织依赖作用org.springframeworkspring-contextSpring IoC 容器Bean 管理org.springframeworkspring-jdbcJdbcTemplate、数据源抽象、事务能力com.h2databaseh2内存数据库零安装零配置org.projectlomboklombok简化 POJO 的 getter / setterch.qos.logbacklogback-classic日志输出调试必备parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion[3.3.11,4.0.0)/version/parentdependenciesdependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactId/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactId/dependencydependencygroupIdcom.h2database/groupIdartifactIdh2/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/dependencydependencygroupIdch.qos.logback/groupIdartifactIdlogback-classic/artifactId/dependency/dependencies三、核心代码演示3.1 外部化配置连接参数抽取到jdbc.propertiesSQL 日志通过 logback 开启方便观察JdbcTemplate执行的 SQL 和参数绑定。# jdbc.properties jdbc.urljdbc:h2:mem:test;DB_CLOSE_DELAY-1;DATABASE_TO_UPPERfalse jdbc.usersa jdbc.password!-- logback.xml --loggernameorg.springframework.jdbclevelDEBUG/loggernameorg.springframework.jdbc.core.StatementCreatorUtilsleveltrace/3.2 JdbcConfig · 手动注册核心 BeanDataSource使用 Spring 内置的DriverManagerDataSource无连接池但足够演示原理。JdbcTemplate依赖DataSource创建所有配置透明可见。ConfigurationComponentScan(com.gzz)PropertySource(classpath:jdbc.properties)publicclassJdbcConfig{Value(${jdbc.url})privateStringurl;Value(${jdbc.user})privateStringuser;Value(${jdbc.password})privateStringpassword;BeanpublicDataSourcedataSource(){returnnewDriverManagerDataSource(url,user,password);}BeanpublicJdbcTemplatejdbcTemplate(){returnnewJdbcTemplate(dataSource());}}3.3 DataInitializer · 启动自动建表插数DataSourceInitializer在容器启动时自动执行data.sql完成建表和测试数据插入。业务代码无需手动初始化数据库。Slf4jConfigurationpublicclassDataInitializer{BeanpublicDataSourceInitializerdataSourceInitializer(DataSourcedataSource){DataSourceInitializerinitializernewDataSourceInitializer();initializer.setDataSource(dataSource);ResourceDatabasePopulatorpopulatornewResourceDatabasePopulator();populator.addScripts(newClassPathResource(data.sql));initializer.setDatabasePopulator(populator);log.info(初始化脚本执行完成);returninitializer;}}-- data.sqlDROPTABLEIFEXISTSt_user;CREATETABLEt_user(idINTAUTO_INCREMENTPRIMARYKEY,nameVARCHAR(32),ageINT);INSERTINTOt_user(name,age)VALUES(张三,10);INSERTINTOt_user(name,age)VALUES(李四,10);INSERTINTOt_user(name,age)VALUES(李四光,20);INSERTINTOt_user(name,age)VALUES(王五,20);3.4 实体 DAO · BeanPropertyRowMapper 一行搞定映射BeanPropertyRowMapper自动将结果集列名映射到实体类的同名字段无需手动遍历ResultSet。SetterGetterpublicclassUser{privateIntegerid;privateStringname;privateIntegerage;}RepositorypublicclassUserDao{AutowiredprivateJdbcTemplatejdbcTemplate;publicListUserqueryUsers(){StringsqlSELECT id, name, age FROM t_user WHERE id ?;returnjdbcTemplate.query(sql,newBeanPropertyRowMapper(User.class),-1);}}id ?中的?是预编译占位符传入-1即查询所有id -1的记录全部数据。预编译占位符从根源上杜绝了 SQL 注入。3.5 Application · 高仿 Spring Boot 启动逻辑手动创建AnnotationConfigApplicationContext传入配置类触发容器启动。EventListener在容器完全就绪后执行查询。Slf4jComponentpublicclassApplication{publicstaticvoidmain(String[]args){newAnnotationConfigApplicationContext(JdbcConfig.class);}AutowiredprivateUserDaodao;EventListener(ContextRefreshedEvent.class)publicvoidrun(){log.info(容器完全启动后执行查询{},dao.queryUsers());}}四、运行结果[INFO] 初始化脚本执行完成 [DEBUG] SELECT id, name, age FROM t_user WHERE id -1 [INFO] 容器完全启动后执行查询[ User(id1, name张三, age10), User(id2, name李四, age10), User(id3, name李四光, age20), User(id4, name王五, age20) ]五、本讲核心总结能力裸 JDBC第 1 讲Spring JDBC本讲连接管理手动DriverManager.getConnection()JdbcTemplate自动管理Statement 创建手动conn.createStatement()JdbcTemplate自动创建结果集遍历手动while(rs.next())BeanPropertyRowMapper一行搞定资源关闭手动逆序关闭JdbcTemplate自动关闭SQL 注入字符串拼接风险高预编译占位符根治代码量30 行2-3 行关键技术点回顾技术点说明spring-jdbc依赖提供JdbcTemplate、数据源抽象、事务能力DriverManagerDataSourceSpring 内置基础数据源适合演示DataSourceInitializer启动时自动执行 SQL 脚本BeanPropertyRowMapper结果集列名 → 实体类同名字段自动映射预编译占位符?从根源上杜绝 SQL 注入六、下一讲预告第 4 讲将引入HikariCP 连接池和DataSourceTransactionManager 事务管理器从“能跑”升级到“生产可用”补齐性能和事务一致性。