目錄
SpringBoot啟動並初始化執行sql腳本
我們先看一下原始碼
下面我們驗證這兩種方式
首頁 Java java教程 SpringBoot如何啟動並初始化執行sql腳本

SpringBoot如何啟動並初始化執行sql腳本

May 13, 2023 am 10:58 AM
sql springboot

    SpringBoot啟動並初始化執行sql腳本

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

    我們先看一下原始碼

    SpringBoot如何啟動並初始化執行sql腳本

    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預設會從類別路徑下去找腳本文件,但是類別路徑下只能放規定名稱為schema或schema-platform的腳本文件,如果我們想要分好多個腳本文件,那麼這種方式就不合適了,那麼就需要我們在application.properties或application.yml中去配置腳本列表,那麼這個初始化腳本操作能不能在設定檔中控制呢,可以的,有一個initialization-mode屬性,可以設定三個值,always為始終執行初始化,embedded只初始化記憶體資料庫(預設值) ,如h3等,never為不執行初始化。

    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的腳本檔案

    SpringBoot如何啟動並初始化執行sql腳本##

    CREATE TABLE IF NOT EXISTS department (ID VARCHAR(40) NOT NULL, NAME VARCHAR(100), PRIMARY KEY (ID));
    登入後複製

    查看資料庫沒有department這個表,接下來我們啟動程式

    SpringBoot如何啟動並初始化執行sql腳本

    啟動之後,我們再看一下,就執行了

    SpringBoot如何啟動並初始化執行sql腳本

    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
    登入後複製

    SpringBoot如何啟動並初始化執行sql腳本

    三個sql腳本都是插入語句

    INSERT INTO department (ID,NAME) VALUES (&#39;1&#39;,&#39;2&#39;)
    INSERT INTO department (ID,NAME) VALUES (&#39;2&#39;,&#39;3&#39;)
    INSERT INTO department (ID,NAME) VALUES (&#39;3&#39;,&#39;4&#39;)
    登入後複製

    現在表中無任何數據,接下來我們啟動程式

    SpringBoot如何啟動並初始化執行sql腳本

    啟動之後,我們再看一下,表中就有了三個資料

    SpringBoot如何啟動並初始化執行sql腳本

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

    SpringBoot專案在啟動時執行指定sql檔

    1. 啟動時執行

    當有在專案啟動時先執行指定的sql語句的需求時,可以在resources資料夾下新增需要執行的sql文件,文件中的sql語句可以是DDL腳本或DML腳本,然後在組態加入對應的組態即可,如下:

    spring:
      datasource:
        schema: classpath:schema.sql # schema.sql中一般存放的是DDL脚本,即通常为创建或更新库表的脚本 data: classpath:data.sql # data.sql中一般是DML脚本,即通常为数据插入脚本
    登入後複製

    2. 執行多個sql檔

    spring.datasource.schema和spring.datasource.data都是支援接收一個列表,所以當需要執行多個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. 不同運行環境執行不同腳本

    一般情況下,都會有多個運行環境,例如開發、測試、生產等。而不同運行環境通常需要執行的sql會有所不同。為解決這個問題,可以使用通配符來實現。

    建立不同環境的資料夾

    在resources資料夾建立不同環境對應的資料夾,如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等。分别对应开发、测试、生产等不同运行环境。
    登入後複製

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

    4. 支援不同資料庫

    因為不同資料庫的語法有所差異,所以要實現同樣的功能,不同資料庫的sql語句可能會不一樣,所以可能會有多份不同的sql檔。當需要支援不同資料庫時,可以使用以下配置:

    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',所以當有在不同資料庫切換的情況下才使用如上配置,因為預設值的情況下,spring boot會自動偵測目前使用的資料庫。

    附註:此時,以dev允許環境為例,resources/dev/資料夾下必須存在下列檔案:schema-mysql.sql和data-mysql.sql。

    5. 避坑

    5.1 坑

    當在執行的sql檔中存在預存程序或函數時,在啟動專案時會報錯。

    例如現在有這樣的需求:專案啟動時,掃描某張表,當表記錄數為0時,插入多筆記錄;大於0時,跳過。

    schema.sql檔案腳本如下:

    -- 当存储过程`p1`存在时,删除。
    drop procedure if exists p1;
     
    -- 创建存储过程`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 (&#39;zhangsan&#39;, &#39;123456&#39;); 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'这一句出现语法错误。刚看到这一句,我一开始是懵逼的,吓得我赶紧去比对mysql存储过程的写法,对了好久都发现没错,最后看到一篇讲解spring boot配置启动时执行sql脚本的文章,发现其中多了一项配置:spring.datasource.separator=$$。然后看源码发现,spring boot在解析sql脚本时,默认是以';'作为断句的分隔符的。看到这里,不难看出报错的原因,即:spring boot把'create procedure p1() begin declare row_num int'当成是一条普通的sql语句。而我们需要的是创建一个存储过程。

    5.2 解决方案

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

    -- 当存储过程`p1`存在时,删除。
    drop procedure if exists p1;$$
     
    -- 创建存储过程`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 (&#39;zhangsan&#39;, &#39;123456&#39;); end if; end;$$ -- 调用存储过程`p1` call p1();$$ drop procedure if exists p1;$$
    登入後複製

    5.3 不足

    因为sql脚本的断句分隔符从';'变成'$$',所以可能需要在DDL、DML语句的';'后加'$$',不然可能会出现将整个脚本当成一条sql语句来执行的情况。比如:

    -- DDL
    CREATE TABLE `table_name` (
      -- 字段定义
      ... 
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;$$
     
    -- DML
    INSERT INTO `table_name` VALUE(...);$$
    登入後複製

    以上是SpringBoot如何啟動並初始化執行sql腳本的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    本網站聲明
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

    熱AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智慧驅動的應用程序,用於創建逼真的裸體照片

    AI Clothes Remover

    AI Clothes Remover

    用於從照片中去除衣服的線上人工智慧工具。

    Undress AI Tool

    Undress AI Tool

    免費脫衣圖片

    Clothoff.io

    Clothoff.io

    AI脫衣器

    Video Face Swap

    Video Face Swap

    使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

    熱工具

    記事本++7.3.1

    記事本++7.3.1

    好用且免費的程式碼編輯器

    SublimeText3漢化版

    SublimeText3漢化版

    中文版,非常好用

    禪工作室 13.0.1

    禪工作室 13.0.1

    強大的PHP整合開發環境

    Dreamweaver CS6

    Dreamweaver CS6

    視覺化網頁開發工具

    SublimeText3 Mac版

    SublimeText3 Mac版

    神級程式碼編輯軟體(SublimeText3)

    Hibernate 框架中 HQL 和 SQL 的差異是什麼? Hibernate 框架中 HQL 和 SQL 的差異是什麼? Apr 17, 2024 pm 02:57 PM

    HQL和SQL在Hibernate框架中進行比較:HQL(1.物件導向語法,2.資料庫無關的查詢,3.類型安全),而SQL直接操作資料庫(1.與資料庫無關的標準,2.可執行複雜查詢和資料操作)。

    Oracle SQL中除法運算的用法 Oracle SQL中除法運算的用法 Mar 10, 2024 pm 03:06 PM

    《OracleSQL中除法運算的用法》在OracleSQL中,除法運算是常見的數學運算之一。在資料查詢和處理過程中,除法運算可以幫助我們計算欄位之間的比例或得出特定數值的邏輯關係。本文將介紹OracleSQL中除法運算的用法,並提供具體的程式碼範例。一、OracleSQL中除法運算的兩種方式在OracleSQL中,除法運算可以用兩種不同的方式來進行

    Oracle與DB2的SQL語法比較與區別 Oracle與DB2的SQL語法比較與區別 Mar 11, 2024 pm 12:09 PM

    Oracle和DB2是兩個常用的關聯式資料庫管理系統,它們都有自己獨特的SQL語法和特性。本文將針對Oracle和DB2的SQL語法進行比較與區別,並提供具體的程式碼範例。資料庫連接在Oracle中,使用以下語句連接資料庫:CONNECTusername/password@database而在DB2中,連接資料庫的語句如下:CONNECTTOdataba

    詳解MyBatis動態SQL標籤中的Set標籤功能 詳解MyBatis動態SQL標籤中的Set標籤功能 Feb 26, 2024 pm 07:48 PM

    MyBatis動態SQL標籤解讀:Set標籤用法詳解MyBatis是一個優秀的持久層框架,它提供了豐富的動態SQL標籤,可以靈活地建構資料庫操作語句。其中,Set標籤是用來產生UPDATE語句中SET子句的標籤,在更新作業中非常常用。本文將詳細解讀MyBatis中Set標籤的用法,以及透過具體的程式碼範例來示範其功能。什麼是Set標籤Set標籤用於MyBati

    SQL中的identity屬性是什麼意思? SQL中的identity屬性是什麼意思? Feb 19, 2024 am 11:24 AM

    SQL中的Identity是什麼,需要具體程式碼範例在SQL中,Identity是一種用於產生自增數字的特殊資料類型,它常用於唯一識別表中的每一行資料。 Identity欄位通常與主鍵列搭配使用,可確保每筆記錄都有獨一無二的識別碼。本文將詳細介紹Identity的使用方式以及一些實際的程式碼範例。 Identity的基本使用方式在建立表格時,可以使用Identit

    SpringBoot與SpringMVC的比較及差別分析 SpringBoot與SpringMVC的比較及差別分析 Dec 29, 2023 am 11:02 AM

    SpringBoot和SpringMVC都是Java開發中常用的框架,但它們之間有一些明顯的差異。本文將探究這兩個框架的特點和用途,並對它們的差異進行比較。首先,我們來了解一下SpringBoot。 SpringBoot是由Pivotal團隊開發的,它旨在簡化基於Spring框架的應用程式的建立和部署。它提供了一種快速、輕量級的方式來建立獨立的、可執行

    SQL出現5120錯誤怎麼解決 SQL出現5120錯誤怎麼解決 Mar 06, 2024 pm 04:33 PM

    解決方法:1、檢查登入使用者是否具有足夠的權限來存取或操作該資料庫,確保該使用者俱有正確的權限;2、檢查SQL Server服務的帳戶是否具有存取指定檔案或資料夾的權限,確保該帳戶具有足夠的權限來讀取和寫入該文件或資料夾;3、檢查指定的資料庫文件是否已被其他進程打開或鎖定,嘗試關閉或釋放該文件,並重新運行查詢;4、嘗試以管理員身份運行Management Studio等等。

    如何使用SQL語句在MySQL中進行資料聚合和統計? 如何使用SQL語句在MySQL中進行資料聚合和統計? Dec 17, 2023 am 08:41 AM

    如何使用SQL語句在MySQL中進行資料聚合和統計?在進行資料分析和統計時,資料聚合和統計是非常重要的步驟。 MySQL作為一個功能強大的關聯式資料庫管理系統,提供了豐富的聚合和統計函數,可以很方便地進行資料聚合和統計操作。本文將介紹使用SQL語句在MySQL中進行資料聚合和統計的方法,並提供具體的程式碼範例。一、使用COUNT函數進行計數COUNT函數是最常用

    See all articles