如何优雅地完成项目数据库的初始化

0 阅读3分钟

简介

当项目在一个新的环境启动或部署时,必不可少的步骤是完成数据库的初始化

将所需要的数据库表,可能还有一些初始的配置数据一次性写入到数据库中

常规的做法,是将初始化脚本整理到项目的资源目录中,提醒开发程序员或者运维人员在部署时手动执行

本文介绍如何优化地完成这个动作,将初始化脚本写入到项目的配置文件中,项目启动时,自动执行该脚本,完成数据库的初始化

配置

简单来说,是在 application.yml 文件中,增加下面这个配置,指定项目启动时加载的数据库脚本

spring:
  # 数据库连接配置(先连接到MySQL服务器,不指定数据库)
  datasource:
    url: jdbc:mysql://localhost:3306/?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

  # 核心配置:自动执行SQL初始化数据库
  sql:
    init:
      # 开启SQL初始化(SpringBoot 2.5+ 默认关闭,必须手动开启)
      mode: always
      # 指定要执行的SQL路径(多个用逗号分隔)
      schema-locations: classpath:init.sql
      # 编码(解决中文乱码)
      encoding: utf-8

init.sql 内容如下,是数据库的初始化脚本,注意这个脚本应设计成幂等的,即多次执行效果相同

具体来说,就是创建前先判断是否存在,存在了就不创建,不存在才创建

-- =============================================
-- 数据库初始化脚本
-- 优雅初始化数据库演示项目
-- =============================================

-- 创建数据库(如果不存在)
CREATE DATABASE IF NOT EXISTS `db_elegant` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 使用该数据库
USE `db_elegant`;

-- 创建用户表(如果不存在)
CREATE TABLE IF NOT EXISTS `db_elegant`.`user` (
    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
    `username` VARCHAR(50) NOT NULL COMMENT '用户名',
    `email` VARCHAR(100) DEFAULT NULL COMMENT '邮箱',
    `age` INT DEFAULT NULL COMMENT '年龄',
    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    PRIMARY KEY (`id`),
    UNIQUE KEY `uk_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

-- 创建商品表(如果不存在)
CREATE TABLE IF NOT EXISTS `db_elegant`.`product` (
    `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
    `name` VARCHAR(100) NOT NULL COMMENT '商品名称',
    `description` VARCHAR(500) DEFAULT NULL COMMENT '商品描述',
    `price` DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT '价格',
    `stock` INT NOT NULL DEFAULT 0 COMMENT '库存',
    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表';

-- 插入测试数据(数据不存在时才插入)
INSERT IGNORE INTO `db_elegant`.`user` (`username`, `email`, `age`) VALUES
('张三', 'zhangsan@example.com', 25),
('李四', 'lisi@example.com', 30),
('王五', 'wangwu@example.com', 28);

INSERT IGNORE INTO `db_elegant`.`product` (`name`, `description`, `price`, `stock`) VALUES
('iPhone 15 Pro', '苹果最新款手机', 8999.00, 100),
('MacBook Pro 14英寸', 'M3芯片专业笔记本', 14999.00, 50),
('AirPods Pro', '主动降噪耳机', 1899.00, 200);

-- 输出初始化完成信息
SELECT '数据库初始化完成!' AS message;

测试

启动项目试一下

在这里插入图片描述

它自己就把数据库脚本执行了

在这里插入图片描述

而且后续接口的查询,也都能查到该数据库的数据,因为在脚本中指定了数据库(USE db_elegant;

在这里插入图片描述