《SpringBoot 3:入门与应用实战》第 12 章 JDBC 与事务 数据库初始化机制 阅读笔记 36

《SpringBoot 3:入门与应用实战》第 12 章 JDBC 与事务 数据库初始化机制 阅读笔记 36

12.6 数据库初始化机制

Spring Boot 在整合 JDBC 时提供了一个比较有趣的初始化机制,它可以在应用启动阶段向连接的数据库发送一些 DDL、DML 语句,以完成创建数据库表、写入表数据等操作。这个机制在使用 H2 等内存数据库时尤为好用,因为内存数据库的特点是启动时没有数据,进程结束后释放内存而造成数据丢失,而数据库的初始化机制可以让内存数据库初始化完成后执行一些 DDL、DML 语句完成初始数据的准备动作,进而减少一些重复的工作。

12.6.1 DDL 语句发送

首先尝试让 Spring Boot 发送 DDL 语句,代码准备了一个部门表 tbl_dept 的建表语句,对于这个建表语句不要直接在 MySQL 中执行,而是将它制作为一个名为 "schema.sql" 的文件,并将其放到工程的 src/main/resources 目录下。schema.sql 这个文件名是 Spring Boot 约定使用的名称,只要 Spring Boot 检测到工程的 src/main/resources 目录下有这个文件,就会加载它并在连接的数据源上执行。

sql 复制代码
CREATE TABLE `tbl_dept` (
                            `id` int(11) NOT NULL AUTO_INCREMENT,
                            `name` varchar(32) DEFAULT NULL COMMENT '部门名称',
                            `pid` int(11) DEFAULT NULL COMMENT '上级部门id',
                            `del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除字段',
                            PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;

随后要在全局配置文件中设置一个配置项:spring.sql.init.mode=always,这代表在任意条件下都执行这个 schema.sql 文件。保存完毕后直接重启整个工程,启动成功后刷新数据库可以看到 tbl_dept 表被创建。

yaml 复制代码
spring:
  application:
    name: springboot-jdbc-a
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.19.201:3306/spring-dao?characterEncoding=utf8
    username: spring-dao
    password: yyy123456.
  sql:
    init:
      mode: always

如果 DDL 语句文件名不是 schema.sql,或者这些文件不在 src/main/resources 目录下,也可以通过设置 spring.sql.init.schema-locations 配置项指定这些文件的位置,注意这个配置项可以传入一个数组。

yaml 复制代码
spring.sql.init.schema-locations[0]=classpath*:sql/schema.sql
spring.sql.init.schema-locations[1]=classpath*:schema.sql

12.6.2 DML语句发送

与执行 DDL 语句的机制类似,执行 DML 语句的约定文件名是 data.sql,只需要在 src/main/resources 目录下再放入一个 data.sql 文件并编写内容,即可在每次工程启动时执行它们。代码中提供了一个插入部门表数据的 SQL,内容比较简单。

sql 复制代码
delete from tbl_dept where del = 0;
insert into tbl_dept (name, pid) values ('总公司', 0);
insert into tbl_dept (name, pid) values ('第一分公司', 1);

如果此时直接重启工程,会发现启动时抛出异常:Table'tbl_dept'already exists,之所以出现这个现象,是因为刚才设置了spring.sql.init.mode=always,这个初始化模式会在每次项目启动时都执行,而同样的建表语句不能连续发送两次,导致抛出了表已存在的异常。解决该问题的方式很简单,只需要在 schema.sql 文件的最开始加入一行 DROP TABLE IF EXISTS tbl_dept; 。

调整后再次重启工程,这次可以在 IDEA 的数据库面板中看到数据库中插入了两条数据,说明 DML 语句也成功执行。

与 schema.sql 文件的配置类似,可以在全局配置文件中设置 spring.sql.init.data-locations 配置项指定 DML 语句的 SQL 文件位置,该配置项同样可以接收一个数组。

12.6.3 多平台兼容与初始化策略

如果工程需要同时考虑对接多种不同的数据库,则有可能因 SQL 语法不兼容导致在一个数据库平台中执行成功,在另一个数据库平台中执行失败。Spring Boot 考虑到了这一点,它支持在 SQL 文件名中添加数据库平台标识来区分不同的类型。例如 schema.sql 代表所有数据库平台中都会执行的 SQL 文件,而 schema-mysql.sql 则代表只有数据源为 MySQL 时才执行的 SQL 文件,schema-oracle.sql 代表数据源为 Oracle 数据库时才执行的 SQL 文件,以此类推,data.sql 同理。

另外解释一下这个数据库初始化机制的使用特点。通过上面的使用过程也能看出,设置 spring.sql.init.mode=always 在连接外部数据库时会产生很大的麻烦,由于每次都要先删掉表后再新建,会导致其中的数据全部丢失,这种使用方式在实际项目开发中是不被允许的,因此 Spring Boot给配置项 spring.sql.init.mode 设置的默认值是 EMBEDDED,即只有在嵌入式数据库中才生效,因为嵌入式数据库就是内存数据库,每次启动时都需要初始化表和数据,刚好可以用得上这个机制。此外还可以设置 spring.sql.init.mode=never 来禁用该初始化机制。

12.7 小结

本章通过使用 Spring Framework 和 Spring Boot 整合 JDBC 完成与数据库的交互操作,并使用 JdbcTemplate 和事务控制完成基本的数据层开发。

Spring Framework 整合 JDBC 所使用的核心包括数据源、数据库访问客户端和事务管理器,在 Spring Boot 中这些组件都基于自动装配完成注册。使用 JdbcTemplate 可以完成简单的数据库 CRUD 操作。Spring Framework 的事务控制包括编程式和声明式,正常的项目开发中更多使用注解声明式事务在 Service 层完成控制。

虽然直接使用 JdbcTemplate 编写 SQL 语句已经简化了与数据库交互的开发,但实际项目开发中更多使用 ORM 框架完成与数据库的交互,第13 章会介绍主流 ORM 框架 MyBatis 在 Spring Boot 项目中的应用。

相关推荐
缓慢更新30 分钟前
表单引擎的存储建模:宽表与文档库的取舍
运维·服务器·网络·数据库·低代码·oracle·适配器模式
小坏讲微服务1 小时前
刚发布一个月的JDK 27,为什么我建议你立刻升级?
java·开发语言·spring boot·spring·架构·求职招聘·springboot4
Web3&Basketball2 小时前
实测Gemini4Argon:ERQA 87%登顶长程任务榜
数据库·python·大模型·多模态·gemini·长上下文·推理优化
xiaogai_gai2 小时前
金蝶收料通知单查询策略实战教程:从源系统拉取到中间层落地的完整路径
java·前端·数据库
注塑机数据采集联网3 小时前
注塑机数据采集网关对接MES系统数字化技术方案
大数据·网络·数据库·物联网·数据挖掘·数据分析
像风一样自由20203 小时前
56.实战PostgreSQL-pgvector-FastAPI构建轻量级RAG
数据库·人工智能·postgresql·大模型·fastapi·智能体
Song_RsHt3 小时前
Gateway(下):过滤器与统一鉴权
spring boot·spring·gateway
TheBlackHoleLab3 小时前
【Vulnhub系列】DarkHole1: 渗透测试笔记,没有踩渗透的坑,却踩到了虚拟机平台的坑,人生处处是大坑
笔记·vulnhub·easy·darkhole1
User_芊芊君子4 小时前
KFS异构同步_260条链路DDL自动转换解析
数据库·ai·大模型
xiancai_xianyu4 小时前
Text2SQL落地生产库前,SQL要过哪三道闸
前端·数据库·sql·sql注入·text2sql·ai agent开发·企业级ai框架