Spring Boot实现第一次启动时自动初始化数据库流程详解

这篇具有很好参考价值的文章主要介绍了Spring Boot实现第一次启动时自动初始化数据库流程详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

package com.gitee.swsk33.sqlinitdemo.config;
import cn.hutool.core.io.resource.ClassPathResource;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
 * 用于第一次启动时,初始化数据库的配置类
 */
@Slf4j
@Configuration
public class DatabaseInitialize {
	/**
	 * 读取连接地址
	 */
	@Value("${spring.datasource.url}")
	private String url;
	/**
	 * 读取用户名
	 */
	@Value("${spring.datasource.username}")
	private String username;
	/**
	 * 读取密码
	 */
	@Value("${spring.datasource.password}")
	private String password;
	/**
	 * 检测当前连接的库是否存在(连接URL中的数据库)
	 *
	 * @return 当前连接的库是否存在
	 */
	private boolean currentDatabaseExists() {
		// 尝试以配置文件中的URL建立连接
		try {
			Connection connection = DriverManager.getConnection(url, username, password);
			connection.close();
		} catch (SQLException e) {
			// 若连接抛出异常则说明连接URL中指定数据库不存在
			return false;
		}
		// 正常情况下说明连接URL中数据库存在
		return true;
	}
	/**
	 * 执行SQL脚本
	 *
	 * @param path        SQL脚本文件的路径
	 * @param isClasspath SQL脚本路径是否是classpath路径
	 * @param connection  数据库连接对象,通过这个连接执行脚本
	 */
	private void runSQLScript(String path, boolean isClasspath, Connection connection) {
		try (InputStream sqlFileStream = isClasspath ? new ClassPathResource(path).getStream() : new FileInputStream(path)) {
			BufferedReader sqlFileStreamReader = new BufferedReader(new InputStreamReader(sqlFileStream, StandardCharsets.UTF_8));
			// 创建SQL脚本执行器对象
			ScriptRunner scriptRunner = new ScriptRunner(connection);
			// 使用SQL脚本执行器对象执行脚本
			scriptRunner.runScript(sqlFileStreamReader);
			// 最后关闭文件读取器
			sqlFileStreamReader.close();
		} catch (Exception e) {
			log.error("读取文件或者执行脚本失败!");
			e.printStackTrace();
		}
	}
	/**
	 * 执行SQL脚本以创建数据库
	 */
	private void createDatabase() {
		try {
			// 修改连接语句,重新建立连接
			// 重新建立的连接不再连接到指定库,而是直接连接到整个MySQL
			// 使用URI类解析并拆解连接地址,重新组装
			URI databaseURI = new URI(url.replace("jdbc:", ""));
			// 得到连接地址中的数据库平台名(例如mysql)
			String databasePlatform = databaseURI.getScheme();
			// 得到连接地址和端口
			String hostAndPort = databaseURI.getAuthority();
			// 得到连接地址中的库名
			String databaseName = databaseURI.getPath().substring(1);
			// 组装新的连接URL,不连接至指定库
			String newURL = "jdbc:" + databasePlatform + "://" + hostAndPort + "/";
			// 重新建立连接
			Connection connection = DriverManager.getConnection(newURL, username, password);
			Statement statement = connection.createStatement();
			// 执行SQL语句创建数据库
			statement.execute("create database if not exists `" + databaseName + "`");
			// 关闭会话和连接
			statement.close();
			connection.close();
			log.info("创建数据库完成!");
		} catch (URISyntaxException e) {
			log.error("数据库连接URL格式错误!");
			throw new RuntimeException(e);
		} catch (SQLException e) {
			log.error("连接失败!");
			throw new RuntimeException(e);
		}
	}
	/**
	 * 该方法用于检测数据库是否需要初始化,如果是则执行SQL脚本进行初始化操作
	 */
	@PostConstruct
	private void initDatabase() {
		log.info("开始检查数据库是否需要初始化...");
		// 检测当前连接数据库是否存在
		if (currentDatabaseExists()) {
			log.info("数据库存在,不需要初始化!");
			return;
		}
		log.warn("数据库不存在!准备执行初始化步骤...");
		// 先创建数据库
		createDatabase();
		// 然后再次连接,执行脚本初始化库中的表格
		try (Connection connection = DriverManager.getConnection(url, username, password)) {
			runSQLScript("/create-table.sql", true, connection);
			log.info("初始化表格完成!");
		} catch (Exception e) {
			log.error("初始化表格时,连接数据库失败!");
			e.printStackTrace();
		}
	}
}

文章来源地址https://www.toymoban.com/news/detail-650198.html

到了这里,关于Spring Boot实现第一次启动时自动初始化数据库流程详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【2023新教程】树莓派4B开机启动-树莓派第一次启动-树莓派不使用显示器启动-树莓派从购买到启动一步一步完全版!

    闲来无事,在咸鱼上买了一个树莓派4B。买来配件都十分齐全,于是就想着启动来测试一下。下面是树莓派无显示器第一次启动的全过程,包含安装系统。 网上的教程大多需要额外使用显示器、鼠标、键盘之类的外设。然而,树莓派本身就是便捷灵活开发的代表,在真实开发

    2024年02月13日
    浏览(50)
  • Spring Boot实现在启动时执行一次的功能

    此方法可能是最常用的 可以使用Spring Boot的@PostConstruct注解来实现在启动时执行一次的功能。@PostConstruct注解标记的方法会在Bean初始化完成后自动调用,可以在该方法中执行只需要在启动时执行一次的操作。 如果想在生成对象时完成某些初始化操作,而偏偏这些初始化操作又

    2024年02月06日
    浏览(27)
  • 第一次使用ThreadPoolTaskExecutor实现线程池的经历,反复修改了多次代码才正常使用

    1、前言   在一个向第三方平台推送消息的场景中,为了提高程序的执行效率,每次发送消息,都创建一个新的线程来完成发送消息的任务,为了提供线程的使用性能,我选择了ThreadPoolTaskExecutor线程池,结果在使用的过程中,出现了较多的问题,这里记录一下避免以后再出

    2024年02月08日
    浏览(41)
  • 当我第一次通过Kotlin和Compose来实现一个Canvas时, 我收获了什么?

    自从2019年Google推荐Kotlin为Android开发的首选语言以来已经经历了将近四年的时间, Compose的1.0版本也发布了将近2年的时间, Kotlin+Compose在现阶段的Android开发过程中还远远达不到主流的程度. 我们是否应该开始尝试这个组合? 这个组合有会给我们带来什么? 对于我来说, 我是个守旧又

    2023年04月27日
    浏览(27)
  • 第一次面试复盘

    这个秋招到目前为止第一次拿到了面试机会,虽然是小公司,但是人家是有官网的!!!很爱!先赶紧复盘一下,因为还有很多笔试没有复盘。 你们的数学建模解决了什么问题?你觉得你们为什么能拿到这个成绩 说下对java这门语言的了解 它是一种面向对象的编程语言,所以

    2024年01月22日
    浏览(34)
  • 树莓派第一次开机

    树莓派由英国的树莓派基金会发行,旨在通过发行这个廉价开源的可随意破解的微型计算机,推动中小学编程教育,发行之后很快在全世界的开源创客圈中流行。截止到2018年10月,最新版本的树莓派主板是3B+,国内某宝上卖230元左右,还有更微型的树莓派主板Zero,国内某宝卖

    2024年02月13日
    浏览(36)
  • 第一次PR经历

         

    2024年02月13日
    浏览(30)
  • shell第一次作业

    1、判断当前磁盘剩余空间是否有20G,如果小于20G,则将报警邮件发送给管理员,每天检查次磁盘剩余空间。 2、判断web服务是否运行    1、查看进程的方式判断该程序是否运行,    2、通过查看端口的方式判断该程序是否运行,如果没有运行,则启动该服务并配置防火墙规

    2024年02月09日
    浏览(37)
  • docker第一次作业

    docker第一次作业 1.安装docker服务,配置镜像加速器  yum install -y yum-utils device-mapper-persistent-data lvm2 y um-config-manager --add-repo https: //mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo sed -i \\\'s+download.docker.com+mirrors.aliyun.com/docker-ce+\\\'  /etc/yum.repos.d/docker-ce.repo yum makecache fast yum -y install docke

    2024年02月12日
    浏览(32)
  • 第一次博客作业

    这学期才开始接触Java,之前只学了C语言,所以一开始写题目的代码的时候对Java的众多函数和语法不是太熟悉,一开始就上手写代码有点不适应。 ​  关于类: 1、类似C中的struct,构造函数、内置方法(函数 )都比较相似 2、尽量避免代码的重复,把private和public的方法搞清晰。

    2024年02月08日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包