最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot啟動(dòng)并初始化執(zhí)行sql腳本問(wèn)題

 更新時(shí)間:2023年01月12日 16:10:23   作者:ITMANLZY  
這篇文章主要介紹了SpringBoot啟動(dòng)并初始化執(zhí)行sql腳本問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

SpringBoot啟動(dòng)并初始化執(zhí)行sql腳本

如果我們想在項(xiàng)目啟動(dòng)的時(shí)候去執(zhí)行一些sql腳本該怎么辦呢,SpringBoot給我們提供了這個(gè)功能,可以在啟動(dòng)SpringBoot的項(xiàng)目時(shí),執(zhí)行腳本,下面我們來(lái)看一下。

我們先看一下源碼

boolean createSchema() {
	//會(huì)從application.properties或application.yml中獲取sql腳本列表
	List<Resource> scripts = this.getScripts("spring.datasource.schema", this.properties.getSchema(), "schema");
    if (!scripts.isEmpty()) {
    	if (!this.isEnabled()) {
        	logger.debug("Initialization disabled (not running DDL scripts)");
            return false;
        }

        String username = this.properties.getSchemaUsername();
        String password = this.properties.getSchemaPassword();
        //運(yùn)行sql腳本
        this.runScripts(scripts, username, password);
    }
    return !scripts.isEmpty();
}
private List<Resource> getScripts(String propertyName, List<String> resources, String fallback) {
	if (resources != null) {
		//如果配置文件中配置,則加載配置文件
    	return this.getResources(propertyName, resources, true);
   	} else {
   		//指定schema要使用的Platform(mysql、oracle),默認(rèn)為all
    	String platform = this.properties.getPlatform();
        List<String> fallbackResources = new ArrayList();
        //如果配置文件中沒(méi)配置,則會(huì)去類(lèi)路徑下找名稱(chēng)為schema或schema-platform的文件
        fallbackResources.add("classpath*:" + fallback + "-" + platform + ".sql");
       	fallbackResources.add("classpath*:" + fallback + ".sql");
       	return this.getResources(propertyName, fallbackResources, false);
    }
}
private List<Resource> getResources(String propertyName, List<String> locations, boolean validate) {
	List<Resource> resources = new ArrayList();
	Iterator var5 = locations.iterator();

    while(var5.hasNext()) {
    	String location = (String)var5.next();
        Resource[] var7 = this.doGetResources(location);
        int var8 = var7.length;

        for(int var9 = 0; var9 < var8; ++var9) {
        	Resource resource = var7[var9];
        	//驗(yàn)證文件是否存在
        	if (resource.exists()) {
            	resources.add(resource);
           	} else if (validate) {
            	throw new InvalidConfigurationPropertyValueException(propertyName, resource, "The specified resource does not exist.");
            }
        }
    }
    return resources;
}

從源碼觀察,大致知道是什么意思了,SpringBoot默認(rèn)會(huì)從類(lèi)路徑下去找腳本文件,但是類(lèi)路徑下只能放規(guī)定名稱(chēng)為schema或schema-platform的腳本文件,如果我們想要分好多個(gè)腳本文件,那么這種方式就不合適了,那么就需要我們?cè)赼pplication.properties或application.yml中去配置腳本列表,那么這個(gè)初始化腳本操作能不能在配置文件中控制呢,可以的,有一個(gè)initialization-mode屬性,可以設(shè)置三個(gè)值,always為始終執(zhí)行初始化,embedded只初始化內(nèi)存數(shù)據(jù)庫(kù)(默認(rèn)值),如h2等,never為不執(zhí)行初始化。

spring:
  datasource:
    username: root
    password: liuzhenyu199577
    url: jdbc:mysql://localhost:3306/jdbc
    driver-class-name: com.mysql.cj.jdbc.Driver
    initialization-mode: always 

下面我們驗(yàn)證一下這兩種方式

1.默認(rèn)放置schema或schema-platform的腳本文件

CREATE TABLE IF NOT EXISTS department (ID VARCHAR(40) NOT NULL, NAME VARCHAR(100), PRIMARY KEY (ID));

查看數(shù)據(jù)庫(kù)沒(méi)有department這個(gè)表,接下來(lái)我們啟動(dòng)程序

啟動(dòng)之后,我們?cè)倏匆幌?,就?zhí)行了

2.配置文件中指定多個(gè)sql腳本

spring:
  datasource:
    username: root
    password: liuzhenyu199577
    url: jdbc:mysql://localhost:3306/jdbc
    driver-class-name: com.mysql.cj.jdbc.Driver
    initialization-mode: always
    schema:
      - classpath:department.sql
      - classpath:department2.sql
      - classpath:department3.sql

三個(gè)sql腳本都是插入語(yǔ)句

INSERT INTO department (ID,NAME) VALUES ('1','2')
INSERT INTO department (ID,NAME) VALUES ('2','3')
INSERT INTO department (ID,NAME) VALUES ('3','4')

現(xiàn)在表中無(wú)任何數(shù)據(jù),接下來(lái)我們啟動(dòng)程序

啟動(dòng)之后,我們?cè)倏匆幌?,表中就有了三條數(shù)據(jù)

就是SpringBoot啟動(dòng)并初始化sql腳本的步驟

SpringBoot項(xiàng)目在啟動(dòng)時(shí)執(zhí)行指定sql文件

1. 啟動(dòng)時(shí)執(zhí)行

當(dāng)有在項(xiàng)目啟動(dòng)時(shí)先執(zhí)行指定的sql語(yǔ)句的需求時(shí),可以在resources文件夾下添加需要執(zhí)行的sql文件,文件中的sql語(yǔ)句可以是DDL腳本或DML腳本,然后在配置加入相應(yīng)的配置即可,如下:

spring:
? datasource:
? ? schema: classpath:schema.sql # schema.sql中一般存放的是DDL腳本,即通常為創(chuàng)建或更新庫(kù)表的腳本 data: classpath:data.sql # data.sql中一般是DML腳本,即通常為數(shù)據(jù)插入腳本?

2. 執(zhí)行多個(gè)sql文件

spring.datasource.schema和spring.datasource.data都是支持接收一個(gè)列表,所以當(dāng)需要執(zhí)行多個(gè)sql文件時(shí),可以使用如下配置:

spring:
? datasource:
? ? schema: classpath:schema_1.sql, classpath:schema_2.sql data: classpath:data_1.sql, classpath:data_2.sql 或 spring: datasource: schema: - classpath:schema_1.sql - classpath:schema_2.sql data: - classpath:data_1.sql - classpath:data_2.sql?

3. 不同運(yùn)行環(huán)境執(zhí)行不同腳本

一般情況下,都會(huì)有多個(gè)運(yùn)行環(huán)境,比如開(kāi)發(fā)、測(cè)試、生產(chǎn)等。而不同運(yùn)行環(huán)境通常需要執(zhí)行的sql會(huì)有所不同。為解決這個(gè)問(wèn)題,可以使用通配符來(lái)實(shí)現(xiàn)。

創(chuàng)建不同環(huán)境的文件夾

在resources文件夾創(chuàng)建不同環(huán)境對(duì)應(yīng)的文件夾,如dev/、sit/、prod/。

配置

application.yml

spring:
? datasource:
? ? schema: classpath:${spring.profiles.active:dev}/schema.sql?
? ? data: classpath:${spring.profiles.active:dev}/data.sql

注:${}通配符支持缺省值。如上面的配置中的${spring.profiles.active:dev},其中分號(hào)前是取屬性spring.profiles.active的值,而當(dāng)該屬性的值不存在,則使用分號(hào)后面的值,即dev。

bootstrap.yml

spring:
? profiles:
? ? active: dev # dev/sit/prod等。分別對(duì)應(yīng)開(kāi)發(fā)、測(cè)試、生產(chǎn)等不同運(yùn)行環(huán)境。

提醒:spring.profiles.active屬性一般在bootstrap.yml或bootstrap.properties中配置。

4. 支持不同數(shù)據(jù)庫(kù)

因?yàn)椴煌瑪?shù)據(jù)庫(kù)的語(yǔ)法有所差異,所以要實(shí)現(xiàn)同樣的功能,不同數(shù)據(jù)庫(kù)的sql語(yǔ)句可能會(huì)不一樣,所以可能會(huì)有多份不同的sql文件。當(dāng)需要支持不同數(shù)據(jù)庫(kù)時(shí),可以使用如下配置:

spring:
? datasource:
? ? schema: classpath:${spring.profiles.active:dev}/schema-${spring.datasource.platform}.sql
? ? data: classpath:${spring.profiles.active:dev}/data-${spring.datasource.platform}.sql
? ? platform: mysql

提醒:platform屬性的默認(rèn)值是'all',所以當(dāng)有在不同數(shù)據(jù)庫(kù)切換的情況下才使用如上配置,因?yàn)槟J(rèn)值的情況下,spring boot會(huì)自動(dòng)檢測(cè)當(dāng)前使用的數(shù)據(jù)庫(kù)。

注:此時(shí),以dev允許環(huán)境為例,resources/dev/文件夾下必須存在如下文件:schema-mysql.sql和data-mysql.sql。

5. 避坑

5.1 坑

當(dāng)在執(zhí)行的sql文件中存在存儲(chǔ)過(guò)程或函數(shù)時(shí),在啟動(dòng)項(xiàng)目時(shí)會(huì)報(bào)錯(cuò)。

比如現(xiàn)在有這樣的需求:項(xiàng)目啟動(dòng)時(shí),掃描某張表,當(dāng)表記錄數(shù)為0時(shí),插入多條記錄;大于0時(shí),跳過(guò)。

schema.sql文件腳本如下:

-- 當(dāng)存儲(chǔ)過(guò)程`p1`存在時(shí),刪除。
drop procedure if exists p1;
?
-- 創(chuàng)建存儲(chǔ)過(guò)程`p1`
create procedure p1()?
begin declare row_num int; select count(*) into row_num from `t_user`; if row_num = 0 then INSERT INTO `t_user`(`username`, `password`) VALUES ('zhangsan', '123456'); end if; end; -- 調(diào)用存儲(chǔ)過(guò)程`p1` call p1(); drop procedure if exists p1;?

啟動(dòng)項(xiàng)目,報(bào)錯(cuò),原因如下:

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'create procedure p1() begin declare row_num int' at line 1

大致的意思是:'create procedure p1() begin declare row_num int'這一句出現(xiàn)語(yǔ)法錯(cuò)誤。剛看到這一句,我一開(kāi)始是懵逼的,嚇得我趕緊去比對(duì)mysql存儲(chǔ)過(guò)程的寫(xiě)法,對(duì)了好久都發(fā)現(xiàn)沒(méi)錯(cuò),最后看到一篇講解spring boot配置啟動(dòng)時(shí)執(zhí)行sql腳本的文章,發(fā)現(xiàn)其中多了一項(xiàng)配置:spring.datasource.separator=$$。然后看源碼發(fā)現(xiàn),spring boot在解析sql腳本時(shí),默認(rèn)是以';'作為斷句的分隔符的??吹竭@里,不難看出報(bào)錯(cuò)的原因,即:spring boot把'create procedure p1() begin declare row_num int'當(dāng)成是一條普通的sql語(yǔ)句。而我們需要的是創(chuàng)建一個(gè)存儲(chǔ)過(guò)程。

5.2 解決方案

修改sql腳本的斷句分隔符。如:spring.datasource.separator=$$。然后把腳本改成:

-- 當(dāng)存儲(chǔ)過(guò)程`p1`存在時(shí),刪除。
drop procedure if exists p1;$$
?
-- 創(chuàng)建存儲(chǔ)過(guò)程`p1`
create procedure p1()?
begin declare row_num int; select count(*) into row_num from `t_user`; if row_num = 0 then INSERT INTO `t_user`(`username`, `password`) VALUES ('zhangsan', '123456'); end if; end;$$ -- 調(diào)用存儲(chǔ)過(guò)程`p1` call p1();$$ drop procedure if exists p1;$$?

5.3 不足

因?yàn)閟ql腳本的斷句分隔符從';'變成'$$',所以可能需要在DDL、DML語(yǔ)句的';'后加'$$',不然可能會(huì)出現(xiàn)將整個(gè)腳本當(dāng)成一條sql語(yǔ)句來(lái)執(zhí)行的情況。比如:

-- DDL
CREATE TABLE `table_name` (
? -- 字段定義
? ...?
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;$$
?
-- DML
INSERT INTO `table_name` VALUE(...);$$

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 使用Guava?Cache原理及最佳實(shí)踐

    使用Guava?Cache原理及最佳實(shí)踐

    文章介紹了GuavaCache,這是一種支持高并發(fā)的本地緩存,它支持多種回收策略,如基于容量、時(shí)間和引用的回收,并提供了自動(dòng)加載、定時(shí)刷新和顯式清除緩存的功能,文章還討論了GuavaCache的適用場(chǎng)景和使用方法,并通過(guò)代碼示例和源碼分析,幫助讀者更好地理解和使用GuavaCache
    2025-02-02
  • Java線程并發(fā)訪問(wèn)代碼分析

    Java線程并發(fā)訪問(wèn)代碼分析

    這篇文章主要介紹了Java線程并發(fā)訪問(wèn)代碼分析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • springmvc Rest風(fēng)格介紹及實(shí)現(xiàn)代碼示例

    springmvc Rest風(fēng)格介紹及實(shí)現(xiàn)代碼示例

    這篇文章主要介紹了springmvc Rest風(fēng)格介紹及實(shí)現(xiàn)代碼示例,rest風(fēng)格簡(jiǎn)潔,分享了HiddenHttpMethodFilter 的源碼,通過(guò)Spring4.0實(shí)現(xiàn)rest風(fēng)格源碼及簡(jiǎn)單錯(cuò)誤分析,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • HttpUtils 發(fā)送http請(qǐng)求工具類(lèi)(實(shí)例講解)

    HttpUtils 發(fā)送http請(qǐng)求工具類(lèi)(實(shí)例講解)

    下面小編就為大家?guī)?lái)一篇HttpUtils 發(fā)送http請(qǐng)求工具類(lèi)(實(shí)例講解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • 詳解 Java中日期數(shù)據(jù)類(lèi)型的處理之格式轉(zhuǎn)換的實(shí)例

    詳解 Java中日期數(shù)據(jù)類(lèi)型的處理之格式轉(zhuǎn)換的實(shí)例

    這篇文章主要介紹了詳解 Java中日期數(shù)據(jù)類(lèi)型的處理之格式轉(zhuǎn)換的實(shí)例的相關(guān)資料,日期以及時(shí)間格式處理,在Java中時(shí)間格式一般會(huì)涉及到的數(shù)據(jù)類(lèi)型包括Calendar類(lèi)和Date類(lèi),需要的朋友可以參考下
    2017-08-08
  • SpringCloud?服務(wù)注冊(cè)中的nacos實(shí)現(xiàn)過(guò)程

    SpringCloud?服務(wù)注冊(cè)中的nacos實(shí)現(xiàn)過(guò)程

    這篇文章主要介紹了SpringCloud?服務(wù)注冊(cè)之nacos實(shí)現(xiàn)過(guò)程,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • HTTPClient如何在Springboot中封裝工具類(lèi)

    HTTPClient如何在Springboot中封裝工具類(lèi)

    這篇文章主要介紹了HTTPClient如何在Springboot中封裝工具類(lèi)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Java并發(fā)工具Fork/Join原理

    Java并發(fā)工具Fork/Join原理

    這篇文章主要為大家介紹了Java并發(fā)工具Fork/Join原理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • 深入分析java文件路徑的詳解

    深入分析java文件路徑的詳解

    本篇文章是對(duì)java文件路徑進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • java使用jna調(diào)用c#中dll的方法詳解

    java使用jna調(diào)用c#中dll的方法詳解

    前一段時(shí)間接了個(gè)項(xiàng)目,需要用到第三方提供的C#編寫(xiě)的dll,本身項(xiàng)目是java語(yǔ)言,所以便有了下面這篇文章,本文給大家介紹了關(guān)于java中如何使用jna調(diào)用c#中dll的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-09-09

最新評(píng)論

德兴市| 新泰市| 香格里拉县| 衡东县| 云霄县| 鸡东县| 香格里拉县| 山阴县| 攀枝花市| 临桂县| 延津县| 寻甸| 浠水县| 永靖县| 海盐县| 泰兴市| 玉环县| 凤凰县| 印江| 江山市| 馆陶县| 长子县| 旅游| 瓦房店市| 娄底市| 隆化县| 确山县| 金昌市| 金溪县| 江川县| 巴彦淖尔市| 石河子市| 佛坪县| 衡东县| 渭南市| 潮州市| 宜君县| 新郑市| 正定县| 天全县| 犍为县|