SpringBoot數(shù)據(jù)庫(kù)初始化datasource配置方式
I. 項(xiàng)目搭建
在我們的日常業(yè)務(wù)開發(fā)過(guò)程中,如果有db的相關(guān)操作,通常我們是直接建立好對(duì)應(yīng)的庫(kù)表結(jié)構(gòu),并初始化對(duì)應(yīng)的數(shù)據(jù),即更常見的情況下是我們?cè)谝延斜斫Y(jié)構(gòu)基礎(chǔ)之下,進(jìn)行開發(fā);
但是當(dāng)我們是以項(xiàng)目形式工作時(shí),更常見的做法是所有的庫(kù)表結(jié)構(gòu)變更、數(shù)據(jù)的初始、更新等都需要持有對(duì)應(yīng)的sql變更,并保存在項(xiàng)目工程中,這也是使用liqubase的一個(gè)重要場(chǎng)景;
將上面的問(wèn)題進(jìn)行簡(jiǎn)單的翻譯一下,就是如何實(shí)現(xiàn)在項(xiàng)目啟動(dòng)之后執(zhí)行相應(yīng)的sql,實(shí)現(xiàn)數(shù)據(jù)庫(kù)表的初始化?
本文將作為初始化方式的第一篇:基于SpringBoot的配置方式實(shí)現(xiàn)的數(shù)據(jù)初始化
1. 依賴
首先搭建一個(gè)標(biāo)準(zhǔn)的SpringBoot項(xiàng)目工程,相關(guān)版本以及依賴如下
本項(xiàng)目借助SpringBoot 2.2.1.RELEASE
+ maven 3.5.3
+ IDEA
進(jìn)行開發(fā)
開一個(gè)web服務(wù)用于測(cè)試
<dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> </dependencies>
本文使用MySql數(shù)據(jù)庫(kù), 版本8.0.31
2. 配置
注意實(shí)現(xiàn)初始化數(shù)據(jù)庫(kù)表操作的核心配置就在下面,重點(diǎn)關(guān)注
配置文件: resources/application.yml
# 默認(rèn)的數(shù)據(jù)庫(kù)名 database: name: story spring: datasource: url: jdbc:mysql://127.0.0.1:3306/${database.name}?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: initialization-mode: always platform: mysql separator: ; data: classpath:config-data.sql #data-username: root #data-password: schema: classpath:config-schema.sql # schema必須也存在,若只存在data,data中的sql也不會(huì)被執(zhí)行 # springboot 2.5+ 版本使用下面這個(gè) # sql: # init: # mode: always # data-location: classpath:config-data.sql # schema-location: classpath:init-schema.sql logging: level: root: info org: springframework: jdbc: core: debug
上面的配置中,相比較于普通的數(shù)據(jù)庫(kù)鏈接配置,多了幾個(gè)配置項(xiàng)
- spring.datasource.initialization-mode: 取值為 always,改成其他的會(huì)導(dǎo)致sql不會(huì)被執(zhí)行
- spring.datasource.platform: mysql
- spring.datasource.seprator: ; 這個(gè)表示sql之間的分隔符
- spring.datasource.data: classpath:config-data.sql 取值可以是數(shù)組,這里存的是初始化數(shù)據(jù)的sql文件地址
- spring.datasource.data-username: 上面data對(duì)應(yīng)的sql文件執(zhí)行用戶名
- spring.datasource.data-password: 上面data對(duì)應(yīng)的sql文件執(zhí)行用戶密碼
- spring.datasource.schema: classpath:config-schema.sql 取值也可以是數(shù)組,這里存的是初始化表結(jié)構(gòu)的sql文件地址
3. 初始化sql
上面指定了兩個(gè)sql,一個(gè)是用于建表的ddl,一個(gè)是用于初始化數(shù)據(jù)的dml
resources/config-schema.sql
文件對(duì)應(yīng)的內(nèi)容如下
CREATE TABLE `user2` ( `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID', `third_account_id` varchar(128) NOT NULL DEFAULT '' COMMENT '第三方用戶ID', `user_name` varchar(64) NOT NULL DEFAULT '' COMMENT '用戶名', `password` varchar(128) NOT NULL DEFAULT '' COMMENT '密碼', `login_type` tinyint NOT NULL DEFAULT '0' COMMENT '登錄方式: 0-微信登錄,1-賬號(hào)密碼登錄', `deleted` tinyint NOT NULL DEFAULT '0' COMMENT '是否刪除', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新時(shí)間', PRIMARY KEY (`id`), KEY `key_third_account_id` (`third_account_id`), KEY `user_name` (`user_name`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='用戶登錄表';
resources/config-data.sql
文件對(duì)應(yīng)的內(nèi)容如下
INSERT INTO `user2` (id, third_account_id, `user_name`, `password`, login_type, deleted) VALUES (2, '222222-0f85-4dd5-845c-7c5df3746e92', 'admin2', 'admin2', 0, 0);
II. 示例
1. 驗(yàn)證demo
接下來(lái)上面的工作準(zhǔn)備完畢之后,在我們啟動(dòng)項(xiàng)目之后,正常就會(huì)執(zhí)行上面的兩個(gè)sql,我們寫一個(gè)簡(jiǎn)單的驗(yàn)證demo
@Slf4j @SpringBootApplication public class Application implements ApplicationRunner { @Autowired private JdbcTemplate jdbcTemplate; public static void main(String[] args) { SpringApplication.run(Application.class); } @Override public void run(ApplicationArguments args) throws Exception { List list = jdbcTemplate.queryForList("select * from user2 limit 2"); log.info("啟動(dòng)成功,初始化數(shù)據(jù): {}\n{}", list.size(), list); } }
2. 問(wèn)題記錄
從上面的過(guò)程走下來(lái),看起來(lái)很簡(jiǎn)單,但是在實(shí)際的使用過(guò)程中,很容易遇到不生效的問(wèn)題,下面記錄一下
2.1 只有初始化數(shù)據(jù)data.sql,沒有schema.sql時(shí),不生效
當(dāng)庫(kù)表已經(jīng)存在時(shí),此時(shí)我們可能并沒有上文中的config-schema.sql
文件,此時(shí)對(duì)應(yīng)的配置可能是
spring: datasource: url: jdbc:mysql://127.0.0.1:3306/${database.name}?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: initialization-mode: always platform: mysql separator: ; # 默認(rèn)為 ; data: classpath:config-data.sql #data-username: root #data-password: #schema: classpath:config-schema.sql # schema必須也存在,若只存在data,data中的sql也不會(huì)被執(zhí)行
如上面所示,當(dāng)我們只指定了data時(shí),會(huì)發(fā)現(xiàn)data對(duì)應(yīng)的sql文件也不會(huì)被執(zhí)行;即要求schema對(duì)應(yīng)的sql文件也必須同時(shí)存在
針對(duì)上面這種情況,可以考慮將data.sql中的語(yǔ)句,卸載schema.sql中
2.2 版本問(wèn)題導(dǎo)致配置不生效
在SpringBoot2.5+版本,使用 spring.sql.init
代替上面的配置項(xiàng)
# springboot 2.5+ 版本使用下面這個(gè) spring: sql: init: mode: always data-location: classpath:config-data.sql schema-location: classpath:init-schema.sql
相關(guān)的配置參數(shù)說(shuō)明如下
spring.sql.init.enabled
:是否啟動(dòng)初始化的開關(guān),默認(rèn)是true。如果不想執(zhí)行初始化腳本,設(shè)置為false即可。通過(guò)-D的命令行參數(shù)會(huì)更容易控制。spring.sql.init.username
和spring.sql.init.password
:配置執(zhí)行初始化腳本的用戶名與密碼。這個(gè)非常有必要,因?yàn)榘踩芾硪螅ǔ=o業(yè)務(wù)應(yīng)用分配的用戶對(duì)一些建表刪表等命令沒有權(quán)限。這樣就可以與datasource中的用戶分開管理。spring.sql.init.schema-locations
:配置與schema變更相關(guān)的sql腳本,可配置多個(gè)(默認(rèn)用;分割)spring.sql.init.data-locations
:用來(lái)配置與數(shù)據(jù)相關(guān)的sql腳本,可配置多個(gè)(默認(rèn)用;分割)spring.sql.init.encoding
:配置腳本文件的編碼spring.sql.init.separator
:配置多個(gè)sql文件的分隔符,默認(rèn)是;spring.sql.init.continue-on-error
:如果執(zhí)行腳本過(guò)程中碰到錯(cuò)誤是否繼續(xù),默認(rèn)是false`
2.3 mode配置不對(duì)導(dǎo)致不生效
當(dāng)配置完之后發(fā),發(fā)現(xiàn)sql沒有按照預(yù)期的執(zhí)行,可以檢查一下spring.datasource.initialization-mode
配置是否存在,且值為always
2.4 重復(fù)啟動(dòng)之后,報(bào)錯(cuò)
同樣上面的項(xiàng)目,在第一次啟動(dòng)時(shí),會(huì)執(zhí)行schema對(duì)應(yīng)的sql文件,創(chuàng)建表結(jié)構(gòu);執(zhí)行data對(duì)應(yīng)的sql文件,初始化數(shù)據(jù);但是再次執(zhí)行之后就會(huì)報(bào)錯(cuò)了,會(huì)提示表已經(jīng)存在
即初始化是一次性的,第一次執(zhí)行完畢之后,請(qǐng)將spring.datasource.initialization-mode
設(shè)置為none
小結(jié)
本文主要介紹了項(xiàng)目啟動(dòng)時(shí),數(shù)據(jù)庫(kù)的初始化方式,當(dāng)然除了本文中介紹的spring.datasource
配置之外,還有spring.jpa
的配置方式
對(duì)于配置方式不太友好的地方則在于不好自適應(yīng)控制,若表存在則不執(zhí)行;若不存在則執(zhí)行;后面將介紹如何使用DataSourceInitializer
來(lái)實(shí)現(xiàn)自主可控的數(shù)據(jù)初始化,以及更現(xiàn)代化一些的基于liquibase的數(shù)據(jù)庫(kù)版本管理記錄
以上就是SpringBoot數(shù)據(jù)庫(kù)初始化datasource配置方式的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot datasource配置的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
淺析JavaWeb項(xiàng)目架構(gòu)之Redis分布式日志隊(duì)列
架構(gòu)、分布式、日志隊(duì)列,標(biāo)題自己都看著唬人,其實(shí)就是一個(gè)日志收集的功能,只不過(guò)中間加了一個(gè)Redis做消息隊(duì)列罷了。下面通過(guò)本文給大家分享JavaWeb項(xiàng)目架構(gòu)之Redis分布式日志隊(duì)列,感興趣的朋友一起看看吧2018-01-01詳細(xì)介紹Java阿里云的短信驗(yàn)證碼實(shí)現(xiàn)
這篇文章主要介紹了詳細(xì)介紹Java阿里云的短信驗(yàn)證碼實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05Spring注解@Profile實(shí)現(xiàn)開發(fā)環(huán)境/測(cè)試環(huán)境/生產(chǎn)環(huán)境的切換
在進(jìn)行軟件開發(fā)過(guò)程中,一般會(huì)將項(xiàng)目分為開發(fā)環(huán)境,測(cè)試環(huán)境,生產(chǎn)環(huán)境。本文主要介紹了Spring如何通過(guò)注解@Profile實(shí)現(xiàn)開發(fā)環(huán)境、測(cè)試環(huán)境、生產(chǎn)環(huán)境的切換,需要的可以參考一下2023-04-04