亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot啟動并初始化執(zhí)行sql腳本問題

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

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

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

我們先看一下源碼

boolean createSchema() {
	//會從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();
        //運行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),默認為all
    	String platform = this.properties.getPlatform();
        List<String> fallbackResources = new ArrayList();
        //如果配置文件中沒配置,則會去類路徑下找名稱為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];
        	//驗證文件是否存在
        	if (resource.exists()) {
            	resources.add(resource);
           	} else if (validate) {
            	throw new InvalidConfigurationPropertyValueException(propertyName, resource, "The specified resource does not exist.");
            }
        }
    }
    return resources;
}

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

下面我們驗證一下這兩種方式

1.默認放置schema或schema-platform的腳本文件

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

查看數(shù)據(jù)庫沒有department這個表,接下來我們啟動程序

啟動之后,我們再看一下,就執(zhí)行了

2.配置文件中指定多個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

三個sql腳本都是插入語句

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)在表中無任何數(shù)據(jù),接下來我們啟動程序

啟動之后,我們再看一下,表中就有了三條數(shù)據(jù)

就是SpringBoot啟動并初始化sql腳本的步驟

SpringBoot項目在啟動時執(zhí)行指定sql文件

1. 啟動時執(zhí)行

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

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

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

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

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. 不同運行環(huán)境執(zhí)行不同腳本

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

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

在resources文件夾創(chuàng)建不同環(huán)境對應的文件夾,如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},其中分號前是取屬性spring.profiles.active的值,而當該屬性的值不存在,則使用分號后面的值,即dev。

bootstrap.yml

spring:
? profiles:
? ? active: dev # dev/sit/prod等。分別對應開發(fā)、測試、生產等不同運行環(huán)境。

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

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

因為不同數(shù)據(jù)庫的語法有所差異,所以要實現(xiàn)同樣的功能,不同數(shù)據(jù)庫的sql語句可能會不一樣,所以可能會有多份不同的sql文件。當需要支持不同數(shù)據(jù)庫時,可以使用如下配置:

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屬性的默認值是'all',所以當有在不同數(shù)據(jù)庫切換的情況下才使用如上配置,因為默認值的情況下,spring boot會自動檢測當前使用的數(shù)據(jù)庫。

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

5. 避坑

5.1 坑

當在執(zhí)行的sql文件中存在存儲過程或函數(shù)時,在啟動項目時會報錯。

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

schema.sql文件腳本如下:

-- 當存儲過程`p1`存在時,刪除。
drop procedure if exists p1;
?
-- 創(chuàng)建存儲過程`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; -- 調用存儲過程`p1` call p1(); drop procedure if exists p1;?

啟動項目,報錯,原因如下:

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)語法錯誤。剛看到這一句,我一開始是懵逼的,嚇得我趕緊去比對mysql存儲過程的寫法,對了好久都發(fā)現(xiàn)沒錯,最后看到一篇講解spring boot配置啟動時執(zhí)行sql腳本的文章,發(fā)現(xiàn)其中多了一項配置:spring.datasource.separator=$$。然后看源碼發(fā)現(xiàn),spring boot在解析sql腳本時,默認是以';'作為斷句的分隔符的??吹竭@里,不難看出報錯的原因,即:spring boot把'create procedure p1() begin declare row_num int'當成是一條普通的sql語句。而我們需要的是創(chuàng)建一個存儲過程。

5.2 解決方案

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

-- 當存儲過程`p1`存在時,刪除。
drop procedure if exists p1;$$
?
-- 創(chuàng)建存儲過程`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;$$ -- 調用存儲過程`p1` call p1();$$ drop procedure if exists p1;$$?

5.3 不足

因為sql腳本的斷句分隔符從';'變成'$$',所以可能需要在DDL、DML語句的';'后加'$$',不然可能會出現(xiàn)將整個腳本當成一條sql語句來執(zhí)行的情況。比如:

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

總結

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Java中內存分配的幾種方法

    Java中內存分配的幾種方法

    本文主要介紹Java中幾種分配內存的方法。我們會看到如何使用sun.misc.Unsafe來統(tǒng)一操作任意類型的內存。以前用C語言開發(fā)的同學通常都希望能在Java中通過較底層的接口來操作內存,他們一定會對本文中要講的內容感興趣
    2014-03-03
  • Nett中的心跳機制與斷線重連詳解

    Nett中的心跳機制與斷線重連詳解

    這篇文章主要介紹了Nett中的心跳機制與斷線重連詳解,我們以客戶端發(fā)送心跳為例,平時我們的心跳實現(xiàn)方式可能是搞個定時器,定時發(fā)送是吧,但是在Netty中卻不一樣,心跳被稱為空閑檢測,需要的朋友可以參考下
    2023-12-12
  • 用IDEA如何打開文件夾

    用IDEA如何打開文件夾

    這篇文章主要介紹了用IDEA如何打開文件夾問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Springboot @Configuration與自動配置詳解

    Springboot @Configuration與自動配置詳解

    這篇文章主要介紹了SpringBoot中的@Configuration自動配置,在進行項目編寫前,我們還需要知道一個東西,就是SpringBoot對我們的SpringMVC還做了哪些配置,包括如何擴展,如何定制,只有把這些都搞清楚了,我們在之后使用才會更加得心應手
    2022-07-07
  • Java(基于Struts2) 分頁實現(xiàn)代碼

    Java(基于Struts2) 分頁實現(xiàn)代碼

    這篇文章介紹了Java(基于Struts2) 分頁實現(xiàn)代碼,有需要的朋友可以參考一下
    2013-10-10
  • Apache?SkyWalking?修復TTL?timer?失效bug詳解

    Apache?SkyWalking?修復TTL?timer?失效bug詳解

    這篇文章主要為大家介紹了Apache?SkyWalking?修復TTL?timer?失效bug詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • SpringBoot 定時任務遇到的坑

    SpringBoot 定時任務遇到的坑

    這篇文章主要介紹了SpringBoot 定時任務遇到的坑,今天踩的這個坑和 cron 表達式有關,文中給大家介紹了cron 表達式的解釋,需要的朋友一起看看吧
    2017-11-11
  • Lombok注解-@SneakyThrows的使用

    Lombok注解-@SneakyThrows的使用

    這篇文章主要介紹了Lombok注解-@SneakyThrows的使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • java中int轉string與string轉int的效率對比

    java中int轉string與string轉int的效率對比

    這篇文章主要介紹了java中int轉string與string轉int的效率對比,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java 實現(xiàn)攔截器Interceptor的攔截功能方式

    Java 實現(xiàn)攔截器Interceptor的攔截功能方式

    這篇文章主要介紹了Java 實現(xiàn)攔截器Interceptor的攔截功能方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10

最新評論