⚡ Spring JDBC 完整体系 · 第 3 讲 · Spring JDBC 最小案例

⚡ Spring JDBC 完整体系 · 第 3 讲 · Spring 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 基础(类、接口、注解、泛型) MyBatis / Hibernate 任何知识
基础 SQL(SELECT、INSERT、WHERE) 连接池原理、事务隔离级别
第 2 讲:Spring 容器(IoC + DI) XML 配置、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(本讲):

对比项 裸 JDBC Spring JDBC
连接管理 手动 DriverManager.getConnection() JdbcTemplate 自动管理
Statement 创建 手动 conn.createStatement() JdbcTemplate 自动创建
结果集遍历 手动 while(rs.next()) + rs.getString() BeanPropertyRowMapper 一行搞定
资源关闭 手动逆序关闭 JdbcTemplate 自动关闭
SQL 注入风险 字符串拼接,风险高 预编译占位符 ?,根治
代码量 30+ 行 2-3 行

二、极简依赖 · spring-context + spring-jdbc 双核驱动

组织 依赖 作用
org.springframework spring-context Spring IoC 容器,Bean 管理
org.springframework spring-jdbc JdbcTemplate、数据源抽象、事务能力
com.h2database h2 内存数据库,零安装零配置
org.projectlombok lombok 简化 POJO 的 getter / setter
ch.qos.logback logback-classic 日志输出,调试必备
xml 复制代码
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>[3.3.11,4.0.0)</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
    </dependency>
</dependencies>

三、核心代码演示

3.1 外部化配置

连接参数抽取到 jdbc.properties,SQL 日志通过 logback 开启,方便观察 JdbcTemplate 执行的 SQL 和参数绑定。

properties 复制代码
# jdbc.properties
jdbc.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false
jdbc.user=sa
jdbc.password=
xml 复制代码
<!-- logback.xml -->
<logger name="org.springframework.jdbc" level="DEBUG" />
<logger name="org.springframework.jdbc.core.StatementCreatorUtils" level="trace" />

3.2 JdbcConfig · 手动注册核心 Bean

DataSource 使用 Spring 内置的 DriverManagerDataSource(无连接池,但足够演示原理)。JdbcTemplate 依赖 DataSource 创建,所有配置透明可见。

java 复制代码
@Configuration
@ComponentScan("com.gzz")
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {

    @Value("${jdbc.url}")      private String url;
    @Value("${jdbc.user}")     private String user;
    @Value("${jdbc.password}") private String password;

    @Bean
    public DataSource dataSource() {
        return new DriverManagerDataSource(url, user, password);
    }

    @Bean
    public JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource());
    }
}

3.3 DataInitializer · 启动自动建表插数

DataSourceInitializer 在容器启动时自动执行 data.sql,完成建表和测试数据插入。业务代码无需手动初始化数据库。

java 复制代码
@Slf4j
@Configuration
public class DataInitializer {

    @Bean
    public DataSourceInitializer dataSourceInitializer(DataSource dataSource) {
        DataSourceInitializer initializer = new DataSourceInitializer();
        initializer.setDataSource(dataSource);

        ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
        populator.addScripts(new ClassPathResource("data.sql"));

        initializer.setDatabasePopulator(populator);
        log.info("初始化脚本执行完成");
        return initializer;
    }
}
sql 复制代码
-- data.sql
DROP TABLE IF EXISTS t_user;
CREATE TABLE t_user (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(32),
    age INT
);
INSERT INTO t_user(name, age) VALUES ('张三', 10);
INSERT INTO t_user(name, age) VALUES ('李四', 10);
INSERT INTO t_user(name, age) VALUES ('李四光', 20);
INSERT INTO t_user(name, age) VALUES ('王五', 20);

3.4 实体 + DAO · BeanPropertyRowMapper 一行搞定映射

BeanPropertyRowMapper 自动将结果集列名映射到实体类的同名字段,无需手动遍历 ResultSet。

java 复制代码
@Setter
@Getter
public class User {
    private Integer id;
    private String name;
    private Integer age;
}
java 复制代码
@Repository
public class UserDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public List<User> queryUsers() {
        String sql = "SELECT id, name, age FROM t_user WHERE id > ?";
        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class), -1);
    }
}

id > ? 中的 ? 是预编译占位符,传入 -1 即查询所有 id > -1 的记录(全部数据)。预编译占位符从根源上杜绝了 SQL 注入。

3.5 Application · 高仿 Spring Boot 启动逻辑

手动创建 AnnotationConfigApplicationContext,传入配置类触发容器启动。@EventListener 在容器完全就绪后执行查询。

java 复制代码
@Slf4j
@Component
public class Application {

    public static void main(String[] args) {
        new AnnotationConfigApplicationContext(JdbcConfig.class);
    }

    @Autowired
    private UserDao dao;

    @EventListener(ContextRefreshedEvent.class)
    public void run() {
        log.info("容器完全启动后执行查询:{}", dao.queryUsers());
    }
}

四、运行结果

log 复制代码
[INFO] 初始化脚本执行完成
[DEBUG] SELECT id, name, age FROM t_user WHERE id > -1
[INFO] 容器完全启动后执行查询:[
    User(id=1, name=张三, age=10),
    User(id=2, name=李四, age=10),
    User(id=3, name=李四光, age=20),
    User(id=4, name=王五, age=20)
]

五、本讲核心总结

能力 裸 JDBC(第 1 讲) Spring JDBC(本讲)
连接管理 手动 DriverManager.getConnection() JdbcTemplate 自动管理
Statement 创建 手动 conn.createStatement() JdbcTemplate 自动创建
结果集遍历 手动 while(rs.next()) BeanPropertyRowMapper 一行搞定
资源关闭 手动逆序关闭 JdbcTemplate 自动关闭
SQL 注入 字符串拼接,风险高 预编译占位符,根治
代码量 30+ 行 2-3 行

关键技术点回顾

技术点 说明
spring-jdbc 依赖 提供 JdbcTemplate、数据源抽象、事务能力
DriverManagerDataSource Spring 内置基础数据源,适合演示
DataSourceInitializer 启动时自动执行 SQL 脚本
BeanPropertyRowMapper 结果集列名 → 实体类同名字段自动映射
预编译占位符 ? 从根源上杜绝 SQL 注入

六、下一讲预告

第 4 讲将引入 HikariCP 连接池 和 DataSourceTransactionManager 事务管理器,从"能跑"升级到"生产可用",补齐性能和事务一致性。

相关推荐
省钱兄--zs1 小时前
24小时自助健身房系统软件开发实战:从架构设计到部署全指南
java·数据仓库·spring boot·系统架构·需求分析
IT研究室1 小时前
最新计算机毕业设计选题推荐-基于spring boot的智慧教学资源管理与互动交流平台-网站-文档指导-Java-springboot
java·spring boot·课程设计
蜗牛互联网1 小时前
Java HttpClient 调用 Gemini 图像理解与金额字段校验
java·开发语言·人工智能·后端·python
开开心心就好1 小时前
视频里的图片怎么提取?双击一下就导出
java·前端·人工智能·spring·智能手机·intellij-idea·excel
蜗牛互联网1 小时前
Python Responses API视觉输入与本地金额校验最小实现
java·开发语言·人工智能·后端·python
程序猿_极客1 小时前
【免费】分享一套优质的基于Java的智慧养老院管理系统的设计与实现(带可视化),源码+文档+视频详解(讲解)
java·spring boot·后端·养老院管理系统
ly76891 小时前
从 TF-IDF 到 BM25:Elasticsearch 相关性评分的字段长度归一化与 boost 调参边界
java·elasticsearch·query dsl·bm25·相关性评分
程序猿_极客2 小时前
【免费】分享一套优质的基于SpringBoot的旅游管理系统的设计与实现(带智能推荐算法功能),源码+文档+视频详解(讲解)
java·spring boot·课程设计·旅游管理系统·计算机专业项目
Wang's Blog2 小时前
Java 中间件之 RabbitMQ 快速入门: RabbitMQ 介绍与安装部署
java·中间件·java-rabbitmq
sibylyue2 小时前
SQLite 运行模式
java·jvm·sqlite