mysql7.x脚本转H2嵌入式数据库,这里脚本指的是使用Navicat、dbeaver 导出的mysql脚本
依赖
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId>
<version>1.11.0</version>
</dependency>
<dependency>
<groupId>com.github.chris2018998</groupId>
<artifactId>beecp</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.3.232</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.8.39</version>
</dependency>
代码
准备好 mysql导出脚本,这里脚本指的是使用Navicat、dbeaver 导出的mysql脚本
package top.lingkang.ma.db;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import com.mybatisflex.core.MybatisFlexBootstrap;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.h2.Driver;
import org.stone.beecp.BeeDataSource;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.sql.Connection;
import java.util.Arrays;
import java.util.List;
import static cn.dev33.satoken.SaManager.log;
/**
* mysql7.x脚本转H2嵌入式数据库,这里脚本指的是使用Navicat、dbeaver 导出的mysql脚本
* <pre>{@code
* public static void main(String[] args) {
* Mysql7ScriptToH2 mysql7ScriptToH2 = new Mysql7ScriptToH2(
* Paths.get(System.getProperty("user.dir"), "sql/dump-mini-202509140144.sql").toFile().getAbsolutePath(),
* "jdbc:h2:C:\\Users\\Administrator\\Desktop\\temp\\testH2",
* null, null
* );
* mysql7ScriptToH2.transform();
* }
* }</pre>
*
* @author lingkang
* created by 2025/9/14 16:14
*/
public class Mysql7ScriptToH2 {
private final File tempOutH2Script = Paths.get(System.getProperty("user.dir"), "sql/h2.sql").toFile();
private final String mysqlScript;
private final String h2Url;
private final String h2Username;
private final String h2Password;
// mysql删除的语法
private static final List<String> removeMysqlGrammar = Arrays.asList(
"CHARACTER SET utf8mb4", "utf8mb4_general_ci", "utf8mb4_0900_ai_ci",
"COLLATE", "unsigned"
);
// 跳过的 startsWith 行
private static final List<String> jumpLineStartsWith = Arrays.asList(
"/*", "--", "LOCK", "UNLOCK",
"BEGIN;", "COMMIT;"
);
public Mysql7ScriptToH2(String mysqlScript, String h2Url, String h2Username, String h2Password) {
this.mysqlScript = mysqlScript;
this.h2Url = h2Url;
this.h2Username = h2Username;
this.h2Password = h2Password;
}
public void transform() {
Assert.isTrue(FileUtil.exist(this.mysqlScript), "mysql script not exist");
Assert.notBlank(this.h2Url, "h2 url not null");
convertMysqlScript();// 转换mysql脚本
BeeDataSource dataSource = new BeeDataSource(
Driver.class.getName(),
h2Url,
h2Username,
h2Password
);
MybatisFlexBootstrap flexBootstrap = MybatisFlexBootstrap.getInstance()
.setDataSource(dataSource)
// .setLogImpl(StdOutImpl.class) //日志输出配置
.start();
// 将 h2 脚本执行到h2数据库
ByteArrayOutputStream logWriter = new ByteArrayOutputStream();
ByteArrayOutputStream errWriter = new ByteArrayOutputStream();
PrintWriter logger = new PrintWriter(logWriter, true);
PrintWriter error = new PrintWriter(errWriter, true);
try (Connection conn = flexBootstrap.getDataSource().getConnection()) {
ScriptRunner runner = new ScriptRunner(conn);
// 设置是否输出日志
// runner.setLogWriter(null); // 不打印SQL日志
runner.setErrorLogWriter(error); // 不打印错误日志
runner.setLogWriter(logger);
// 读取SQL文件
File sqlFile = Paths.get(System.getProperty("user.dir"), "sql/h2.sql").toFile();
Reader reader = new BufferedReader(new FileReader(sqlFile));
// 执行脚本
runner.runScript(reader);
reader.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
log.info("execute sql: {}", logWriter.toString(StandardCharsets.UTF_8));
log.info("execute sql error: {}", errWriter.toString(StandardCharsets.UTF_8));
IoUtil.close(logWriter);
IoUtil.close(error);
}
// List<Row> rows = Db.selectAll("gen_templates");
// System.out.println(rows);
}
/**
* 转换mysql特有的类型、字符等
*/
private String convertMysqlLine(String line) {
for (String remove : removeMysqlGrammar) {
if (line.contains(remove)) {
line = line.replace(remove, "");
}
}
if (line.contains("bigint unsigned")) {
line = line.replace("bigint unsigned", "bigint");
}
if (line.contains("datetime")) {
line = line.replace("datetime", "TIMESTAMP");
}
if (line.contains("text")) {
line = line.replace("text", "LONGVARCHAR");
}
return line.trim();
}
private void convertMysqlScript() {
List<String> list = FileUtil.readUtf8Lines(mysqlScript);
StringBuilder sb = new StringBuilder();
StringBuilder insert = new StringBuilder();
StringBuilder index = new StringBuilder();
String tableName = "";
boolean startTable = false;
for (int i = 0; i < list.size(); i++) {
String str = list.get(i);
if (isJumpLine(str))
continue;
if (str.startsWith("INSERT INTO")) {
// 排除指定表数据插入
str = str.replace("\\'", "''");// 转义 \'
insert.append(str).append("\n\n");
continue;
}
if (str.startsWith("CREATE TABLE")) {
startTable = true;
// CREATE TABLE `sys_config` (
tableName = str.trim().split(" ")[2];
}
if (startTable && str.startsWith(") ENGINE")) {
// 结束处理表注释
if (str.contains("COMMENT=")) {
String comment = str.substring(str.indexOf("COMMENT=") + 8).trim();
str = ");";
str += "\n" + "COMMENT ON TABLE " + tableName + " IS " + comment + "\n";
}
// 判断前一行是否存在 分号
char topEnd = sb.charAt(sb.length() - 2);
if (topEnd == ',') {
// 删除上面的 分号
sb.delete(sb.length() - 2, sb.length()).append('\n');
}
startTable = false;
}
if (startTable) {
str = convertMysqlLine(str);
if (str.contains("PRIMARY KEY ")) {
// PRIMARY KEY (`user_id`,`role_id`) USING BTREE
String end = str.endsWith(",") ? "," : "";
if (str.contains("USING")) {
str = str.substring(0, str.indexOf("USING"));
} else if (",".equals(end)) {
str = str.substring(0, str.indexOf(","));
}
if (",".equals(end)) {// 说明下面的有索引
// KEY `sys_dict_data_label_IDX` (`label`) USING BTREE,
// KEY `sys_dict_data_value_IDX` (`dict_value`) USING BTREE
int j = 1;
String line = list.get(i + j);
while (line.contains("KEY ")) {
j++;
String[] split = line.split("`");
// CREATE INDEX email_send_smtp_id_IDX ON email_send (smtp_id);
index.append("CREATE INDEX ")
.append(split[1])
.append(" ON ")
.append(tableName)
.append(" (`")
.append(split[3])
.append("`);\n");
line = list.get(i + j);
}
}
}
if (str.startsWith("KEY ")) {
continue;
}
}
sb.append(str).append("\n");
}
sb.append("\n\n\n")
.append(index)
.append("\n\n\n")
.append(insert);
tempOutH2Script.delete();
FileUtil.writeUtf8String(sb.toString(), tempOutH2Script);
}
private boolean isJumpLine(String str) {
str = str.trim();
for (String jump : jumpLineStartsWith) {
if (str.startsWith(jump)) {
return true;
}
}
return false;
}
public static void main(String[] args) {
Mysql7ScriptToH2 mysql7ScriptToH2 = new Mysql7ScriptToH2(
Paths.get(System.getProperty("user.dir"), "sql/dump-mini-202509140144.sql").toFile().getAbsolutePath(),
"jdbc:h2:C:\\Users\\Administrator\\Desktop\\temp\\testH2",
null, null
);
mysql7ScriptToH2.transform();
}
}