启动程序触发器-项目启动建表

一、需求

  • 在项目启动时,自动新建数据表

二、实现思路

  • 创建触发类

  • 实现SpringBoot的ApplicationRunner接口

  • 编写建表语句常量

  • 实现run方法,并在run方法中使用JDBC工具类的建表方法,传入建表语句常亮,完成建表

三、代码实现(末尾附完整代码)

  • 创建触发类,实现ApplicationRunner接口
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;

/**
 * 项目启动的程序触发器
 *
 * @author Odinpeng
 * @since 2023/11/29
 **/

@Slf4j
@Component
@Order(0) //表示触发的顺序,越小越靠前
public class TableBuildingTrigger implements ApplicationRunner {}

注:

  • 一个项目可以有多个启动触发器

  • @Order的value属性表示启动触发器的执行顺序

  • value属性越小,该启动触发器的执行顺序越靠前(可以为负数)

  • 编写建表语句常量
    // 建表语句1
    private static final String USER_TABLE = "CREATE TABLE user_table "
            + "( id Integer NOT NULL COMMENT 'id',"
            + " username varchar(20) NOT NULL COMMENT '用户名',"
            + " password varchar(4) NOT NULL COMMENT '密码',"
            + " PRIMARY KEY (id) ) COMMENT='用户表'";

    // 建表语句2
    private static final String ORDER_TABLE = "CREATE TABLE order_table "
            + "( id Integer NOT NULL COMMENT 'id',"
            + " orderName varchar(20) NOT NULL COMMENT '订单名',"
            + " price Integer NOT NULL COMMENT '价格',"
            + " PRIMARY KEY (id) ) COMMENT='订单表'";
  • 引入JDBC工具类,实现ApplicationRunner接口的run方法完成建表
	// 重写run方法
	@Override
    public void run(ApplicationArguments args) throws Exception {
        // 将表名和建表语句存入map
        HashMap<String, String> tableMap = new HashMap<String, String>() {{
            put("user_table", USER_TABLE);
            put("order_table", ORDER_TABLE);
        }};
        // 遍历建表
        tableMap.forEach((key, value) -> {
            //执行建表方法,在建表方法中判断当前表是否存在
            if (!checkTable(key, value)) {
                log.error("初始化{}核心配置表失败,执行sql:{}", key, value);
                throw new BizException("建表失败");
            }
        });

    }

    /**
     * 检查表是否存在,不存在新建表
     *
     * @param tableName 表名
     * @param createSql 建表语句
     * @return
     */
    private boolean checkTable(String tableName, String createSql) {
        // 查询指定表名的数量
        String sql = "select count(table_name) from information_schema.tables where table_name like '%s'";
        // 将表名动态拼接到以上sql中
        String querySql = String.format(sql, tableName);
        Integer total = jdbcTemplate.queryForObject(querySql, Integer.class);
        // 若查询指定表名的数量<=0,说明当前表不存在,则新增表
        if (total <= 0) {
            // 查询当前数据库版本
            String versionSql = "select version()";
            String version = jdbcTemplate.queryForObject(versionSql, String.class);
            // 若当前数据库版本为5.7开头,则将字符集由"utf8mb4"替换为"utf8"(MySQL5.7默认字符集是"utf8mb4",支持4字节字符,而utf8支持3字节)
            if (version.startsWith("5.7")) {
                createSql = createSql.replaceAll("utf8mb4", "utf8");
            }
            // 新建表
            int update = jdbcTemplate.update(createSql);
            if (update <= 0) {
                return false;
            }
        }
        return true;
    }

四、完整代码

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;

/**
 * 项目启动的程序触发器
 *
 * @author Odinpeng
 * @since 2023/11/29
 **/

@Slf4j
@Component
@Order(0) //表示触发的顺序,越小越靠前
public class TableBuildingTrigger implements ApplicationRunner {

    // 引入JDBC工具类,用于建表和查询表是否存在
    @Resource
    private JdbcTemplate jdbcTemplate;

    // 建表语句1
    private static final String USER_TABLE = "CREATE TABLE user_table "
            + "( id Integer NOT NULL COMMENT 'id',"
            + " username varchar(20) NOT NULL COMMENT '用户名',"
            + " password varchar(4) NOT NULL COMMENT '密码',"
            + " PRIMARY KEY (id) ) COMMENT='用户表'";

    // 建表语句2
    private static final String ORDER_TABLE = "CREATE TABLE order_table "
            + "( id Integer NOT NULL COMMENT 'id',"
            + " orderName varchar(20) NOT NULL COMMENT '订单名',"
            + " price Integer NOT NULL COMMENT '价格',"
            + " PRIMARY KEY (id) ) COMMENT='订单表'";

    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 将表名和建表语句存入map
        HashMap<String, String> tableMap = new HashMap<String, String>() {{
            put("user_table", USER_TABLE);
            put("order_table", ORDER_TABLE);
        }};
        // 遍历建表,并查询表是否存在
        tableMap.forEach((key, value) -> {
            //执行建表方法,在建表方法中判断当前表是否存在
            if (!checkTable(key, value)) {
                log.error("初始化{}核心配置表失败,执行sql:{}", key, value);
                throw new BizException("建表失败");
            }
        });
    }

    /**
     * 检查表是否存在,不存在新建表
     *
     * @param tableName 表名
     * @param createSql 建表语句
     * @return
     */
    private boolean checkTable(String tableName, String createSql) {
        // 查询指定表名的数量
        String sql = "select count(table_name) from information_schema.tables where table_name like '%s'";
        // 将表名动态拼接到以上sql中
        String querySql = String.format(sql, tableName);
        Integer total = jdbcTemplate.queryForObject(querySql, Integer.class);
        // 若查询指定表名的数量<=0,说明当前表不存在,则新增表
        if (total <= 0) {
            // 查询当前数据库版本
            String versionSql = "select version()";
            String version = jdbcTemplate.queryForObject(versionSql, String.class);
            // 若当前数据库版本为5.7开头,则将字符集由"utf8mb4"替换为"utf8"(MySQL5.7默认字符集是"utf8mb4",支持4字节字符,而utf8支持3字节)
            if (version.startsWith("5.7")) {
                createSql = createSql.replaceAll("utf8mb4", "utf8");
            }
            // 新建表
            int update = jdbcTemplate.update(createSql);
            if (update <= 0) {
                return false;
            }
        }
        return true;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值