前几天Spring Boot 2.5.0发布了,其中提到了关于Datasource初始化机制的调整,有读者私信想了解这方面做了什么调整 。那么今天就要详细说说这个重新设计的配置内容,并结合实际情况说说我的理解和实践建议 。
弃用内容先来纠正一个误区 。主要之前在版本更新介绍的时候,存在一些表述上的问题 。导致部分读者认为这次的更新是Datasource本身初始化的调整,但其实并不是 。这次重新设计的只是对Datasource脚本初始化机制的重新设计 。
先来看看这次被弃用部分的内容(位于org.springframework.boot.autoconfigure.jdbc.DataSourceProperties),如果你有用过这些配置内容,那么新配置就很容易理解了 。
/*** Mode to apply when determining if DataSource initialization should be performed* using the available DDL and DML scripts.*/ @Deprecated private DataSourceInitializationMode initializationMode = DataSourceInitializationMode.EMBEDDED; /*** Platform to use in the DDL or DML scripts (such as schema-${platform}.sql or* data-${platform}.sql).*/ @Deprecated private String platform = "all"; /*** Schema (DDL) script resource references.*/ private List<String> schema; /*** Username of the database to execute DDL scripts (if different).*/ @Deprecated private String schemaUsername; /*** Password of the database to execute DDL scripts (if different).*/ @Deprecated private String schemaPassword; /*** Data (DML) script resource references.*/ @Deprecated private List<String> data; /*** Username of the database to execute DML scripts (if different).*/ @Deprecated private String dataUsername; /*** Password of the database to execute DML scripts (if different).*/ @Deprecated private String dataPassword; /*** Whether to stop if an error occurs while initializing the database.*/ @Deprecated private boolean continueOnError = false; /*** Statement separator in SQL initialization scripts.*/ @Deprecated private String separator = ";"; /*** SQL scripts encoding.*/ @Deprecated private Charset sqlScriptEncoding;对应到配置文件里的属性如下(这里仅列出部分,就不全部列出了,主要就是对应上面源码中的属性):
spring.datasource.schema=spring.datasource.schema-username=spring.datasource.schema-password=...这些配置主要用来指定数据源初始化之后要用什么用户、去执行哪些脚本、遇到错误是否继续等功能 。
新的设计Spring Boot 2.5.0开始,启用了全新的配置方式,我们可以从这个类org.springframework.boot.autoconfigure.sql.init.SqlInitializationProperties里看到详情 。
下面我们通过一个简单的例子来体验这个功能的作用 。
- 创建一个Spring Boot的基础应用,并在pom.xml中引入和mysql的依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency>- 在配置文件中增加数据源和初始化数据源的配置,具体如下:
spring.datasource.url=jdbc:mysql://localhost:3306/testspring.datasource.username=rootspring.datasource.password=spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver# Spring Boot 2.5.0 init schema & data# 执行初始化脚本的用户名称spring.sql.init.username=root# 执行初始化脚本的用户密码spring.sql.init.password=# 初始化的schema脚本位置spring.sql.init.schema-locations=classpath*:schema-all.sql- 根据上面配置的定义,接下来就在
resource目录下,创建脚本文件schema-all.sql,并写入一些初始化表结构的脚本
create table test.user_info(idint unsigned auto_increment comment '用户id'primary key,open_idvarchar(255)default '' null comment '微信小程序openid',nick_namevarchar(255)default '' null comment '微信名',head_imgvarchar(255)default '' null comment '微信头像',sexvarchar(255)default '' null comment '性别',phonevarchar(255)default '' null comment '手机',provincevarchar(255)default '' null comment '注册地址:省',cityvarchar(255)default '' null comment '注册地址:城市',countryvarchar(255)default '' null comment '注册地址:县/区',statustinyint unsigned default 0not null comment '是否标记删除 0:否 1:是',create_time datetimenot null comment '创建时间',update_time datetimenot null comment '更新时间')comment '用户表';- 完成上面步骤之后,启动应用 。然后打开MySQL客户端,可以看到在
test库下,多了一个user_info表
配置详解除了上面用到的配置属性之外,还有一些其他的配置,下面详细讲解一下作用 。
spring.sql.init.enabled:是否启动初始化的开关,默认是true 。如果不想执行初始化脚本,设置为false即可 。通过-D的命令行参数会更容易控制 。spring.sql.init.username和spring.sql.init.password:配置执行初始化脚本的用户名与密码 。这个非常有必要,因为安全管理要求,通常给业务应用分配的用户对一些建表删表等命令没有权限 。这样就可以与datasource中的用户分开管理 。spring.sql.init.schema-locations:配置与schema变更相关的sql脚本,可配置多个(默认用;分割)spring.sql.init.data-locations:用来配置与数据相关的sql脚本,可配置多个(默认用;分割)spring.sql.init.encoding:配置脚本文件的编码spring.sql.init.separator:配置多个sql文件的分隔符,默认是;spring.sql.init.continue-on-error:如果执行脚本过程中碰到错误是否继续,默认是false`;所以,上面的例子第二次执行的时候会报错并启动失败,因为第一次执行的时候表已经存在 。
那么依靠这些配置,是否可以胜任业务应用部署时候数据库初始化的自动化实现呢?
个人认为就上述所介绍的配置,虽然具备了一定的自动执行能力 。但由于缺失对当前环境的判断能力,所以要应对实际的部署场景来说,还是远远不够的 。
如果要自动化的管理数据库表结构、初始化数据的话,我的建议是:
- 默认提供的这个初始化功能可以且仅用于单元测试,自动创建数据库结构与初始化数据,使用完毕后销毁 。可以方便的控制每次单元测试的执行环境一致 。
- 应用在环境部署的时候,还是要使用之前介绍过的Flyway来实现,如何使用可见之前的分享:使用Flyway来管理数据库版本 。
- 联合Flyway一同使用,通过
org.springframework.jdbc.datasource.init.DataSourceInitializer来定义更复杂的执行逻辑 。
代码示例本文的相关例子可以查看下面仓库中的
chapter3-13目录:- Github:https://github.com/dyc87112/SpringBoot-Learning/
- Gitee:https://gitee.com/didispace/SpringBoot-Learning/
Star支持,您的关注是我坚持的动力!欢迎关注我的公众号:程序猿DD,分享外面看不到的干货与思考!
- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
