⚡ Spring JDBC 完整体系 · 第 5 讲 · Spring Boot Starter JDBC

⚡ Spring JDBC 完整体系 · 第 5 讲 · Spring Boot Starter JDBC

相关开源地址:

  1. 核心框架源码:https://gitee.com/gao_zhenzhong/simple-dao
  2. 系统底座:https://gitee.com/gao_zhenzhong/simple-dao-starter
  3. 代码生成器:https://gitee.com/gao_zhenzhong/simple-dao-coder
  4. 实战案例(本集源码):https://gitee.com/gao_zhenzhong/simple-dao-demo

📋 前置知识

你只需要会 你完全不需要会
Java 基础(类、接口、注解) Spring Boot 自动配置源码细节
第 4 讲:连接池 + 事务管理器 条件注解 @Conditional 底层原理
Spring Boot 基础用法(@SpringBootApplication) 自定义 Starter 开发

📚 全套教程总览(20 讲从零到架构师)

篇章 涵盖讲次 核心目标
开篇筑基 第 1-3 讲 认知梳理,建立 Spring JDBC 的底层坐标系
API 精讲 第 4-7 讲 全面掌握 JdbcTemplate + 事务体系
工具封装 第 8-9 讲 手搓条件工具 + 代码生成器,从"使用者"变"创造者"
认知升华 第 10 讲 模板确定性 vs AI 不确定性,建立技术判断力
高阶扩展 第 11-17 讲 多数据源、分库分表、分布式事务
底层观测 第 18-19 讲 SQL 拦截、性能监控、连接池调优
终极收尾 第 20 讲 全链路复盘 + 手搓持久层框架

一、开篇 · 从 40 行配置到 0 行配置

第 4 讲手动引入了 spring-context、spring-jdbc、HikariCP 三个依赖,手动注册了四个 Bean:

Bean 作用
DataSource HikariCP 连接池
JdbcTemplate SQL 操作模板
TransactionManager 事务管理器
DataSourceInitializer 初始化数据

这一讲引入 spring-boot-starter-jdbc,看一个依赖如何等价替代上述所有手动工作。

Starter 的本质:依赖聚合 + 条件化自动装配。

二、依赖对比 · 上集 vs 本集

上集:手动引入 3 个依赖

依赖 作用
spring-context Spring IoC 容器
spring-jdbc JdbcTemplate + 事务抽象
HikariCP 连接池

本集:1 个 Starter 搞定一切

xml 复制代码
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>[3.3.11,4.0.0)</version>
</parent>

<dependencies>
    <!-- 一个 starter 聚合了 spring-jdbc + HikariCP + spring-tx -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <!-- 数据库驱动 -->
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
    </dependency>
    <!-- 简化代码 -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

三、核心代码演示

3.1 application.yml · 标准配置文件

只需配置数据源 URL 和 SQL 初始化脚本,其他全部自动:

yaml 复制代码
spring:
  datasource:
    url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
    driver-class-name: org.h2.Driver
    username: sa
    password:

  sql:
    init:
      schema-locations: classpath:schema.sql    # 启动时执行建表脚本
      mode: always

3.2 schema.sql · 初始数据

sql 复制代码
DROP TABLE IF EXISTS sys_user;
CREATE TABLE sys_user (
    id BIGINT PRIMARY KEY COMMENT '主键',
    name VARCHAR(50) COMMENT '姓名',
    birthday DATE COMMENT '生日',
    gender TINYINT COMMENT '性别',
    loginTime TIMESTAMP COMMENT '登录时间'
);

INSERT INTO sys_user VALUES (1, '郭靖', '2018-07-13', 1, '2022-05-20 11:43:54');
INSERT INTO sys_user VALUES (2, '洪七公', '2018-07-13', 1, '2022-05-20 11:43:58');

3.3 logback-spring.xml · 日志格式与 SQL 参数打印

开启 JdbcTemplate 的 DEBUG 日志,观察 SQL 执行情况;开启 StatementCreatorUtils 的 TRACE 日志,查看参数绑定细节:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>[%p][%F:%L]:%m%n</pattern>
        </encoder>
    </appender>

    <logger name="org.springframework.jdbc.core.JdbcTemplate" level="debug" />
    <logger name="org.springframework.jdbc.core.StatementCreatorUtils" level="trace" />

    <root level="info">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

3.4 User.java · 用户实体

java 复制代码
@Data
public class User {
    private Long id;
    private String name;
    private LocalDate birthday;
    private Byte gender;
    private LocalDateTime loginTime;
}

3.5 UserDao.java · 用户数据访问类

@PostConstruct 在 Bean 初始化后自动执行查询,BeanPropertyRowMapper 一行完成映射:

java 复制代码
@Slf4j
@Repository
public class UserDao {

    @Autowired
    protected JdbcTemplate jdbcTemplate;

    @PostConstruct
    public void demo() {
        String sql = "SELECT t.id, t.name, t.birthday, t.gender, t.loginTime " +
                     "FROM sys_user t WHERE t.id > ? ORDER BY t.id";
        jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class), 0)
                     .forEach(u -> log.info("user={}", u));
    }
}

3.6 Application.java · Spring Boot 标准启动类

java 复制代码
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

四、运行结果

log 复制代码
[INFO] HikariPool-1 - Start completed.
[DEBUG] SELECT t.id, t.name, t.birthday, t.gender, t.loginTime FROM sys_user t WHERE t.id > ? ORDER BY t.id
[TRACE] column index 1, parameter value [0], value class [java.lang.Integer]
[INFO] user=User(id=1, name=郭靖, birthday=2018-07-13, gender=1, loginTime=2022-05-20T11:43:54)
[INFO] user=User(id=2, name=洪七公, birthday=2018-07-13, gender=1, loginTime=2022-05-20T11:43:58)

五、为什么能跑?(一)依赖聚合

执行 mvn dependency:tree 查看依赖树:

log 复制代码
[INFO] com.gzz:05-starter-jdbc:jar:1.0
[INFO] +- org.springframework.boot:spring-boot-starter-jdbc:jar:4.1.0:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:4.1.0:compile
[INFO] |  +- org.springframework:spring-jdbc:jar:7.0.8:compile
[INFO] |  +- org.springframework:spring-context:jar:7.0.8:compile
[INFO] |  |  \- org.springframework:spring-tx:jar:7.0.8:compile
[INFO] |  \- com.zaxxer:HikariCP:jar:7.0.2:compile

一个 spring-boot-starter-jdbc 自动传递了 spring-jdbc、HikariCP、spring-tx------第 4 讲手动引入的依赖全部被 Starter 聚合带入了。

六、为什么能跑?(二)自动配置

在 spring-boot-starter-jdbc 的 spring-boot-jdbc.jar 包中,META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件预置了自动配置类:

log 复制代码
org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration
org.springframework.boot.jdbc.autoconfigure.DataSourceInitializationAutoConfiguration
org.springframework.boot.jdbc.autoconfigure.DataSourceTransactionManagerAutoConfiguration
org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration

配置类对应关系

自动配置类 自动创建的 Bean 对应第 4 讲手动代码
DataSourceAutoConfiguration HikariDataSource @Bean DataSource
JdbcTemplateAutoConfiguration JdbcTemplate @Bean JdbcTemplate
DataSourceTransactionManagerAutoConfiguration DataSourceTransactionManager @Bean TransactionManager
DataSourceInitializationAutoConfiguration DataSourceInitializer @Bean DataSourceInitializer

spring-boot-starter-jdbc 自动完成了第 4 讲全部 4 个 Bean 的注册,这就是条件化自动装配的价值。

自动配置如何与 application.yml 联动?

application.yml 中的配置项(如 spring.datasource.url)被 Spring Boot 的 @ConfigurationProperties 机制绑定到 DataSourceProperties 对象,自动配置类通过 @EnableConfigurationProperties(DataSourceProperties.class) 读取这些值,再注入到 HikariDataSource 实例中。整个过程对开发者完全透明,只需按规范填写配置即可。

数据初始化配置映射

application.yml 中的两行配置:

yaml 复制代码
spring.sql.init:
  schema-locations: classpath:schema.sql
  mode: always

被绑定到 DataSourceInitializationProperties,DataSourceInitializationAutoConfiguration 据此创建 DataSourceInitializer Bean,在容器启动时执行指定的 SQL 脚本。这也是自动配置的一环。

七、上集 vs 本集 · 代码量对比

对比项 第 4 讲(手动) 第 5 讲(Starter)
Maven 依赖 3 个 1 个
配置类 JdbcConfig.java(40+ 行) 无,全部自动
DataSource 手动 new HikariDataSource() 自动创建
JdbcTemplate 手动 new JdbcTemplate() 自动创建
TransactionManager 手动 new DataSourceTransactionManager() 自动创建
数据初始化 手动 DataSourceInitializer application.yml 两行配置
启动类 AnnotationConfigApplicationContext SpringApplication.run()

八、本讲核心总结

Starter 做了什么 本质
依赖聚合 一个依赖自动引入 spring-jdbc + HikariCP + spring-tx
自动创建 DataSource DataSourceAutoConfiguration
自动创建 JdbcTemplate JdbcTemplateAutoConfiguration
自动创建 TransactionManager DataSourceTransactionManagerAutoConfiguration
自动创建 DataSourceInitializer DataSourceInitializationAutoConfiguration
外部化配置 application.yml 一行配置,自动读取并绑定

Starter = 依赖聚合 + 条件化自动装配

延伸思考:如果只有一个数据源,为什么还需要手动注册?

spring-boot-starter-jdbc 的设计前提是"约定优于配置"------一个 Spring Boot 应用默认只有一个数据源,自动配置类通过 @ConditionalOnMissingBean 注解保证:如果开发者没有手动定义 DataSource 等 Bean,Spring Boot 才自动创建。这套机制兼顾了开箱即用和自定义扩展两种场景。

九、下一讲预告

第 6 讲将全面展开 JdbcTemplate API 细讲 ------query(单条、列表、标量)、update(增删改)、batchUpdate(批量操作),深入 PreparedStatement 回调和 RowMapper 体系。

相关推荐
代码什么用3 小时前
Spring基础使用
java·后端·spring
代码什么用3 小时前
Spring对IoC的实现
数据库·spring
Su米苏3 小时前
Spring AI 中MCP 与普通 @Tool的区别
java·人工智能·spring
码云数智-园园3 小时前
unique_ptr 还是 shared_ptr?C++ 智能指针选型与内存泄漏实战分析
java·开发语言
老板一杯拿铁3 小时前
Java 异常体系详解:从字节码原理到最佳实践
java
蜗牛互联网3 小时前
Java 17 HttpClient调用文件转写API的超时与失败回退
java·人工智能·后端
禾小西4 小时前
07丨Redis 哨兵机制:主库故障后,如何恢复服务?
java·开发语言·redis
我不是阵雨4 小时前
JDK 21虚拟线程Pinning陷阱:一文拔钉解困
java·开发语言
小卡车5554 小时前
java反射、自定义注解的应用(自定义分页)
java
BLUcoding5 小时前
接口服务公网超时排查记录:SecureRandom 阻塞问题分析与解决
java·linux·springboot·aes·securerandom