谷粒商城实战笔记-一键执行项目SQL脚本


课程提供了项目的初始化脚本。

在这里插入图片描述
但是要手动逐个建库,执行脚本,还是比较费时间的。

特别是因为虚拟机或者其他原因,学习过程中需要多次初始化数据库,逐个手动执行,很影响效率。

所以,这里写了个Java脚本,一键完成建库、建表、插入初始化数据的工作。

package com.lcy.exercise.mysql;

import cn.hutool.core.util.StrUtil;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;

public class SqlScriptExecutor {

    private static final String DB_URL = "jdbc:mysql://47.11.7.59:3306/";
    private static final String USER = "root"; // 请替换为实际的用户名
    private static final String PASS = "68bed551"; // 请替换为实际的密码

    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            File folder = new File("D:\\BaiduNetdiskDownload\\GuliMall_Resources\\GuliMall\\gulimall\\db");

            for (File file : folder.listFiles()) {
                if (file.isFile() && file.getName().endsWith(".sql")) {
                    executeSqlScript(file);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void executeSqlScript(File file) throws Exception {
        String dbName = file.getName().replace(".sql", "");
        System.out.println(StrUtil.format("当前数据库:{}", dbName));
        boolean dbExists = checkIfDatabaseExists(dbName);

        Connection conn = null;
        try {
            // 如果数据库不存在,则创建它
            if (!dbExists) {
                conn = DriverManager.getConnection(StrUtil.format("{}?useSSL=false",DB_URL), USER, PASS);
                Statement stmt = conn.createStatement();
                stmt.executeUpdate("CREATE DATABASE " + dbName);
                stmt.close();
            }

            // 连接到数据库
            conn = DriverManager.getConnection(StrUtil.format("{}{}?useSSL=false",DB_URL, dbName), USER, PASS);
            Statement stmt = conn.createStatement();

            // 读取SQL脚本文件
            // Read SQL script file
            try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
                StringBuilder sqlCommand = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    sqlCommand.append(line).append('\n');
                    if (line.trim().endsWith(";")) {
                        executeSqlCommand(stmt, sqlCommand.toString());
                        sqlCommand.setLength(0); // Reset StringBuilder
                    }
                }
            } catch (IOException e) {
                System.out.println("Error reading file: " + e.getMessage());
            }
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
    }

    private static boolean checkIfDatabaseExists(String dbName) throws Exception {
        Connection conn = DriverManager.getConnection(StrUtil.format("{}?useSSL=false",DB_URL), USER, PASS);
        Statement stmt = conn.createStatement();
        String query = "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '" + dbName + "'";
        ResultSet rs = stmt.executeQuery(query);
        boolean exists = rs.next();
        rs.close();
        stmt.close();
        conn.close();
        return exists;
    }

    private static void executeSqlCommand(Statement stmt, String sqlCommand) {
        try {
            stmt.execute(sqlCommand);
//            System.out.println("Executed: " + sqlCommand);
        } catch (Exception e) {
            System.out.println("Error executing SQL command: " + sqlCommand);
            e.printStackTrace();
        }
    }
}

下面详细地分析一下上面提供的Java代码。

代码结构概述

  1. 主类定义 - 定义了一个名为SqlScriptExecutor的公共类。
  2. 主方法 (main 方法) - 这是程序的入口点,它遍历指定目录下的所有文件。
  3. 执行SQL脚本的方法 (executeSqlScript) - 这个方法负责连接到数据库、创建数据库(如果不存在)、读取并执行SQL脚本文件中的命令。
  4. 执行SQL命令的方法 (executeSqlCommand) - 这个方法用于执行单条SQL命令,并捕获可能发生的异常。

详细解释

1. 主方法 (main 方法)
public static void main(String[] args) {
    String path = "D:\\BaiduNetdiskDownload\\GuliMall_Resources\\GuliMall\\gulimall\\db";
    File directory = new File(path);

    if (!directory.exists() || !directory.isDirectory()) {
        System.out.println("Directory does not exist or is not a directory.");
        return;
    }

    for (File file : directory.listFiles()) {
        if (file.isFile() && file.getName().endsWith(".sql")) {
            String dbName = file.getName().substring(0, file.getName().indexOf('.'));
            executeSqlScript(file, dbName);
        }
    }
}
  • path 变量存储了要读取的目录路径。
  • 创建一个 File 对象 directory 来表示该目录。
  • 检查该路径是否存在并且确实是一个目录。如果不是,打印一条消息并退出程序。
  • 使用 listFiles() 方法获取目录下的所有文件,并遍历它们。
  • 对于每一个文件,检查它是否是一个 .sql 文件,如果是,则获取文件名(不包括扩展名),这通常会被认为是数据库的名称,并调用 executeSqlScript 方法来处理该文件。
2. 执行SQL脚本的方法 (executeSqlScript 方法)
private static void executeSqlScript(File file, String dbName) {
    try (Connection conn = DriverManager.getConnection(DB_URL + dbName, USER, PASS)) {
        // Check if the database exists and create it if necessary
        Statement stmt = conn.createStatement();
        String checkDbQuery = "CREATE DATABASE IF NOT EXISTS `" + dbName + "`";
        stmt.executeUpdate(checkDbQuery);

        // Read SQL script file
        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            StringBuilder sqlCommand = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                sqlCommand.append(line).append('\n');
                if (line.trim().endsWith(";")) {
                    executeSqlCommand(stmt, sqlCommand.toString());
                    sqlCommand.setLength(0); // Reset StringBuilder
                }
            }
        } catch (IOException e) {
            System.out.println("Error reading file: " + e.getMessage());
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 使用 DriverManager.getConnection() 方法建立与数据库的连接。
  • 使用 createStatement() 方法创建一个 Statement 对象。
  • 执行 CREATE DATABASE IF NOT EXISTS 语句来确保数据库存在。
  • 使用 BufferedReader 从文件中逐行读取内容。
  • 将读取的内容追加到 StringBuilder 中,直到遇到分号 ; 结束符。
  • 当遇到分号时,调用 executeSqlCommand 方法执行SQL命令,并清空 StringBuilder 准备接收下一个SQL命令。
3. 执行SQL命令的方法 (executeSqlCommand 方法)
private static void executeSqlCommand(Statement stmt, String sqlCommand) {
    try {
        stmt.execute(sqlCommand);
        System.out.println("Executed: " + sqlCommand);
    } catch (Exception e) {
        System.out.println("Error executing SQL command: " + sqlCommand);
        e.printStackTrace();
    }
}
  • 使用 stmt.execute(sqlCommand) 方法执行SQL命令。
  • 如果执行成功,打印出执行的SQL命令。
  • 如果执行失败,打印出错误信息和堆栈跟踪。

注意事项

  • 在实际应用中,建议使用更强大的SQL解析库来处理复杂的SQL语句,特别是当SQL语句中有注释或嵌套的引号时。
  • 连接字符串、用户名和密码应该通过安全的方式传递,而不是硬编码在代码中。
  • 代码中未包含详细的错误处理逻辑,如网络连接失败等情况,实际使用时应添加适当的异常处理。
  • 20
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小手追梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值