Heim >Java >javaLernprogramm >Wie SpringBoot die Ausführung von SQL-Skripten startet und initialisiert
Was sollen wir tun, wenn wir beim Start des Projekts einige SQL-Skripte ausführen möchten? SpringBoot stellt uns diese Funktion zur Verfügung, mit der das Skript beim Starten des SpringBoot-Projekts ausgeführt werden kann Schauen wir uns unten um.
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; }
Aus dem Quellcode wissen wir ungefähr, was es bedeutet, dass SpringBoot standardmäßig Skriptdateien aus dem Klassenpfad findet, aber nur der angegebene Name kann darunter platziert werden Klassenpfad: Schema oder Schema-Plattform-Skriptdatei. Wenn wir sie in mehrere Skriptdateien aufteilen möchten, ist diese Methode nicht geeignet. Dann müssen wir die Skriptliste in application.properties oder application.yml konfigurieren. Dann kann dies geschehen Der Initialisierungsskriptvorgang kann in der Datei konfiguriert werden. Ja, es gibt ein Initialisierungsmodusattribut, das auf drei Werte eingestellt werden kann, was immer bedeutet, dass die Initialisierung immer ausgeführt wird. Die eingebettete Funktion initialisiert nur die Speicherdatenbank (Standardwert). wie h3 usw. und bedeutet niemals, dass keine Initialisierung durchgeführt wird.
spring: datasource: username: root password: liuzhenyu199577 url: jdbc:mysql://localhost:3306/jdbc driver-class-name: com.mysql.cj.jdbc.Driver initialization-mode: always
1. Die Skriptdatei des Schemas oder der Schemaplattform wird standardmäßig platziert
CREATE TABLE IF NOT EXISTS department (ID VARCHAR(40) NOT NULL, NAME VARCHAR(100), PRIMARY KEY (ID));
Überprüfen Sie, ob die Datenbank keine Abteilungstabelle enthält, und starten Sie dann das Programm
Lassen Sie uns nach dem Start einen weiteren Blick darauf werfen und es ausführen
2. In der Konfigurationsdatei sind mehrere SQL-Skripte angegeben die Tabelle, als nächstes Nachdem wir das Programm gestartet haben
, werfen wir noch einmal einen Blick darauf. Die Tabelle enthält drei Datenelemente
Dies ist der Schritt zum Starten von SpringBoot und zum Initialisieren des SQL-Skripts
Die Das SpringBoot-Projekt führt die angegebene SQL-Datei beim Start aus
1. Beim Start ausführen
Wenn beim Starten des Projekts zuerst die angegebene SQL-Anweisung ausgeführt werden muss, können Sie die auszuführende SQL-Datei unter den Ressourcen hinzufügen Die SQL-Anweisung in der Datei kann ein DDL-Skript oder ein DML-Skript sein. Fügen Sie dann einfach die entsprechende Konfiguration wie folgt hinzu: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.sql2 Führen Sie mehrere SQL-Dateien ausspring.datasource.schema .datasource.data unterstützen beide den Empfang einer Liste. Wenn also mehrere SQL-Dateien ausgeführt werden müssen, können Sie die folgende Konfiguration verwenden:
INSERT INTO department (ID,NAME) VALUES ('1','2') INSERT INTO department (ID,NAME) VALUES ('2','3') INSERT INTO department (ID,NAME) VALUES ('3','4')
Erstellen Sie Ordner für verschiedene Umgebungen.
Erstellen Sie Ordner für verschiedene Umgebungen im Ressourcenordner, z. B. dev/, sit/, prod/.Configuration
application.ymlspring: datasource: schema: classpath:schema.sql # schema.sql中一般存放的是DDL脚本,即通常为创建或更新库表的脚本 data: classpath:data.sql # data.sql中一般是DML脚本,即通常为数据插入脚本Hinweis: Der Platzhalter ${} unterstützt den Standardwert. Beispielsweise soll ${spring.profiles.active:dev} in der obigen Konfiguration vor dem Semikolon den Wert des Attributs spring.profiles.active annehmen, und wenn der Wert des Attributs nicht vorhanden ist, wird der Wert danach verwendet Semikolon wird verwendet, das ist dev.
bootstrap.yml
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.sqlErinnerung: Die spring.profiles.active-Eigenschaft wird im Allgemeinen in bootstrap.yml oder bootstrap.properties konfiguriert. 4. Unterstützen Sie verschiedene DatenbankenDa die Syntax verschiedener Datenbanken unterschiedlich ist, können die SQL-Anweisungen verschiedener Datenbanken unterschiedlich sein, um dieselbe Funktion zu erreichen, sodass möglicherweise mehrere verschiedene SQL-Dateien vorhanden sind. Wenn Sie verschiedene Datenbanken unterstützen müssen, können Sie die folgende Konfiguration verwenden:
spring: datasource: schema: classpath:${spring.profiles.active:dev}/schema.sql data: classpath:${spring.profiles.active:dev}/data.sqlZur Erinnerung: Der Standardwert des Plattformattributs ist „all“. Verwenden Sie daher die obige Konfiguration nur beim Wechsel zwischen verschiedenen Datenbanken, da mit dem Standardwert Spring Boot erkennt automatisch die aktuell verwendete Datenbank. Hinweis: Zu diesem Zeitpunkt müssen, wenn man die von Entwicklern zugelassene Umgebung als Beispiel nimmt, die folgenden Dateien im Ordner resources/dev/ vorhanden sein: schema-mysql.sql und data-mysql.sql. 5. Fallstricke vermeiden
5.1 Fallstricke
Wenn in der ausgeführten SQL-Datei gespeicherte Prozeduren oder Funktionen vorhanden sind, wird beim Starten des Projekts ein Fehler gemeldet. Zum Beispiel gibt es jetzt eine solche Anforderung: Wenn das Projekt beginnt, scannen Sie eine bestimmte Tabelle. Wenn die Anzahl der Datensätze in der Tabelle 0 ist, fügen Sie mehrere Datensätze ein. Das Skript der Dateischema.sql lautet wie folgt:
spring: profiles: active: dev # dev/sit/prod等。分别对应开发、测试、生产等不同运行环境。Starten Sie das Projekt und melden Sie einen Fehler. Der Grund ist wie folgt:
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(...);$$
Das obige ist der detaillierte Inhalt vonWie SpringBoot die Ausführung von SQL-Skripten startet und initialisiert. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!