Heim >Java >javaLernprogramm >Wie SpringBoot die Ausführung von SQL-Skripten startet und initialisiert

Wie SpringBoot die Ausführung von SQL-Skripten startet und initialisiert

WBOY
WBOYnach vorne
2023-05-13 10:58:122767Durchsuche

    SpringBoot startet und initialisiert die Ausführung von SQL-Skripten

    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.

    Schauen wir uns zuerst den Quellcode an

    Wie SpringBoot die Ausführung von SQL-Skripten startet und initialisiert

    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

    Lassen Sie uns diese beiden Methoden überprüfen

    1. Die Skriptdatei des Schemas oder der Schemaplattform wird standardmäßig platziert

    Wie SpringBoot die Ausführung von SQL-Skripten startet und initialisiert

    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

    Wie SpringBoot die Ausführung von SQL-Skripten startet und initialisiert

    Lassen Sie uns nach dem Start einen weiteren Blick darauf werfen und es ausführen

    Wie SpringBoot die Ausführung von SQL-Skripten startet und initialisiert

    2. In der Konfigurationsdatei sind mehrere SQL-Skripte angegeben die Tabelle, als nächstes Nachdem wir das Programm gestartet haben

    Wie SpringBoot die Ausführung von SQL-Skripten startet und initialisiert

    , werfen wir noch einmal einen Blick darauf. Die Tabelle enthält drei Datenelemente

    Wie SpringBoot die Ausführung von SQL-Skripten startet und initialisiertDies 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ührenWie SpringBoot die Ausführung von SQL-Skripten startet und initialisiert

    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.sql

    2 Führen Sie mehrere SQL-Dateien aus

    spring.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 (&#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;)

    3 Verschiedene Betriebsumgebungen führen unterschiedliche Skripte aus

    Im Allgemeinen gibt es mehrere Betriebsumgebungen, z wie Entwicklung, Test, Produktion usw. Das SQL, das normalerweise in verschiedenen Betriebsumgebungen ausgeführt werden muss, ist unterschiedlich. Um dieses Problem zu lösen, können Platzhalter verwendet werden.

    Erstellen Sie Ordner für verschiedene Umgebungen.

    Erstellen Sie Ordner für verschiedene Umgebungen im Ressourcenordner, z. B. dev/, sit/, prod/.

    Configuration

    application.yml

    spring:
      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.sql

    Erinnerung: Die spring.profiles.active-Eigenschaft wird im Allgemeinen in bootstrap.yml oder bootstrap.properties konfiguriert.

    4. Unterstützen Sie verschiedene Datenbanken

    Da 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.sql

    Zur 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 Datei

    schema.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 (&#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(...);$$

    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!

    Stellungnahme:
    Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen