SpringBoot如何啟動並初始化執行sql腳本
SpringBoot啟動並初始化執行sql腳本
如果我們想在專案啟動的時候去執行一些sql腳本該怎麼辦呢,SpringBoot給我們提供了這個功能,可以在啟動SpringBoot的專案時,執行腳本,下面我們來看看。
我們先看一下原始碼
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的腳本檔案
##
CREATE TABLE IF NOT EXISTS department (ID VARCHAR(40) NOT NULL, NAME VARCHAR(100), PRIMARY KEY (ID));
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
INSERT INTO department (ID,NAME) VALUES ('1','2') INSERT INTO department (ID,NAME) VALUES ('2','3') INSERT INTO department (ID,NAME) VALUES ('3','4')
spring: datasource: schema: classpath:schema.sql # schema.sql中一般存放的是DDL脚本,即通常为创建或更新库表的脚本 data: classpath:data.sql # data.sql中一般是DML脚本,即通常为数据插入脚本
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
建立不同環境的資料夾
在resources資料夾建立不同環境對應的資料夾,如dev/、sit/、prod/。設定
application.ymlspring: datasource: schema: classpath:${spring.profiles.active:dev}/schema.sql data: classpath:${spring.profiles.active:dev}/data.sql
spring: profiles: active: dev # dev/sit/prod等。分别对应开发、测试、生产等不同运行环境。
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
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 ('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'这一句出现语法错误。刚看到这一句,我一开始是懵逼的,吓得我赶紧去比对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 ('zhangsan', '123456'); 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中文網其他相關文章!

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

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

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

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

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

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

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

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

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

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