一、需求
- 在项目启动时,自动新建数据表
二、实现思路
-
创建触发类
-
实现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;
}
}