Files
yjearth/src/main/java/com/yj/earth/common/util/SQLiteConverter.java

246 lines
9.3 KiB
Java
Raw Normal View History

2025-09-29 17:34:21 +08:00
package com.yj.earth.common.util;
import cn.hutool.core.lang.UUID;
2025-09-29 13:56:36 +08:00
import java.sql.*;
2025-09-29 17:34:21 +08:00
import java.time.LocalDateTime;
2025-09-29 13:56:36 +08:00
public class SQLiteConverter {
private static final String JDBC_DRIVER = "org.sqlite.JDBC";
2025-09-29 17:34:21 +08:00
// 源数据库和目标数据库路径
private String sourceDbPath;
private String targetDbPath;
// 批处理大小、可根据内存情况调整
private static final int BATCH_SIZE = 100;
public SQLiteConverter(String sourceDbPath, String targetDbPath) {
this.sourceDbPath = sourceDbPath;
this.targetDbPath = targetDbPath;
}
2025-09-29 13:56:36 +08:00
2025-09-29 17:34:21 +08:00
public void convert() {
Connection sourceConn = null;
Connection targetConn = null;
try {
// 加载驱动
Class.forName(JDBC_DRIVER);
// 连接源数据库和目标数据库
sourceConn = DriverManager.getConnection("jdbc:sqlite:" + sourceDbPath);
targetConn = DriverManager.getConnection("jdbc:sqlite:" + targetDbPath);
// 禁用自动提交、以便在出现错误时可以回滚
targetConn.setAutoCommit(false);
// 创建目标表结构
createTargetTables(targetConn);
// 复制并转换数据
copyModeTypesData(sourceConn, targetConn);
copyModelsData(sourceConn, targetConn);
// 为model表添加索引
createModelTableIndexes(targetConn);
// 提交事务
targetConn.commit();
System.out.println("数据库转换成功!");
} catch (Exception e) {
2025-09-29 13:56:36 +08:00
e.printStackTrace();
2025-09-29 17:34:21 +08:00
try {
if (targetConn != null) {
targetConn.rollback();
System.out.println("转换失败、已回滚操作!");
}
} catch (SQLException ex) {
ex.printStackTrace();
}
} finally {
// 关闭连接
try {
if (sourceConn != null) sourceConn.close();
if (targetConn != null) targetConn.close();
} catch (SQLException e) {
e.printStackTrace();
}
2025-09-29 13:56:36 +08:00
}
}
2025-09-29 17:34:21 +08:00
private void createTargetTables(Connection conn) throws SQLException {
System.out.println("开始创建目标表结构...");
Statement stmt = conn.createStatement();
String sql = """
CREATE TABLE "model_type" (
"id" TEXT,
"name" TEXT,
"parent_id" TEXT,
"tree_index" INTEGER,
"created_at" TEXT,
"updated_at" TEXT,
PRIMARY KEY ("id")
);
""";
stmt.execute(sql);
sql = """
CREATE TABLE "model" (
"id" TEXT,
"model_type_id" TEXT,
"model_name" TEXT,
"model_type" TEXT,
"model_data" BLOB,
"poster_type" TEXT,
"poster_data" BLOB,
"created_at" TEXT,
"updated_at" TEXT,
PRIMARY KEY ("id")
);
""";
stmt.execute(sql);
stmt.close();
System.out.println("目标表结构创建完成");
2025-09-29 13:56:36 +08:00
}
/**
2025-09-29 17:34:21 +08:00
* model 表的每个字段创建索引
2025-09-29 13:56:36 +08:00
*/
2025-09-29 17:34:21 +08:00
private void createModelTableIndexes(Connection conn) throws SQLException {
System.out.println("开始为创建索引...");
Statement stmt = conn.createStatement();
String sql = """
CREATE INDEX idx_model_covering ON model(
model_type_id,
id,
model_name,
model_type,
poster_type,
created_at,
updated_at
);
""";
stmt.execute(sql);
stmt.close();
System.out.println("model表索引创建完成");
}
2025-09-29 13:56:36 +08:00
2025-09-29 17:34:21 +08:00
private int getTotalRecords(Connection conn, String tableName) throws SQLException {
PreparedStatement stmt = conn.prepareStatement("SELECT COUNT(*) AS total FROM " + tableName);
ResultSet rs = stmt.executeQuery();
int total = rs.next() ? rs.getInt("total") : 0;
rs.close();
stmt.close();
return total;
2025-09-29 13:56:36 +08:00
}
2025-09-29 17:34:21 +08:00
private void copyModeTypesData(Connection sourceConn, Connection targetConn) throws SQLException {
int totalRecords = getTotalRecords(sourceConn, "mode_types");
System.out.println("开始转换 mode_types 表数据、共" + totalRecords + "条记录");
PreparedStatement sourceStmt = sourceConn.prepareStatement("SELECT * FROM mode_types");
ResultSet rs = sourceStmt.executeQuery();
PreparedStatement targetStmt = targetConn.prepareStatement(
"INSERT INTO model_type (id, name, parent_id, tree_index, created_at, updated_at) " +
"VALUES (?, ?, ?, ?, ?, ?)"
);
int count = 0;
while (rs.next()) {
targetStmt.setString(1, rs.getString("type_id"));
targetStmt.setString(2, rs.getString("type_name"));
targetStmt.setString(3, rs.getString("p_id"));
targetStmt.setInt(4, 0);
targetStmt.setObject(5, LocalDateTime.now());
targetStmt.setObject(6, LocalDateTime.now());
// 添加到批处理
targetStmt.addBatch();
count++;
// 每达到批处理大小或最后一条记录时执行批处理
if (count % BATCH_SIZE == 0 || count == totalRecords) {
targetStmt.executeBatch();
displayProgress(count, totalRecords, "mode_types 表");
}
2025-09-29 13:56:36 +08:00
}
2025-09-29 17:34:21 +08:00
System.out.println("\n成功转换 mode_types 表数据:" + count + "条记录");
rs.close();
sourceStmt.close();
targetStmt.close();
}
2025-09-29 13:56:36 +08:00
2025-09-29 17:34:21 +08:00
private void copyModelsData(Connection sourceConn, Connection targetConn) throws SQLException {
int totalRecords = getTotalRecords(sourceConn, "models");
System.out.println("开始转换 models 表数据、共" + totalRecords + "条记录");
// 对于大字段、使用向前滚动的结果集、避免缓存所有数据
PreparedStatement sourceStmt = sourceConn.prepareStatement(
"SELECT * FROM models",
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY
);
sourceStmt.setFetchSize(100);
ResultSet rs = sourceStmt.executeQuery();
PreparedStatement targetStmt = targetConn.prepareStatement(
"INSERT INTO model (id, model_type_id, model_name, model_type, model_data, " +
"poster_type, poster_data, created_at, updated_at) " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"
);
int count = 0;
while (rs.next()) {
targetStmt.setString(1, rs.getString("id"));
targetStmt.setString(2, rs.getString("p_id"));
targetStmt.setString(3, rs.getString("model_name"));
targetStmt.setString(4, rs.getString("model_type"));
byte[] dataBytes = rs.getBytes("data");
if (dataBytes != null) {
targetStmt.setBytes(5, dataBytes);
} else {
targetStmt.setNull(5, Types.BLOB);
}
targetStmt.setString(6, rs.getString("poster_type"));
byte[] posterBytes = rs.getBytes("poster");
if (posterBytes != null) {
targetStmt.setBytes(7, posterBytes);
}
targetStmt.setObject(8, LocalDateTime.now());
targetStmt.setObject(9, LocalDateTime.now());
// 添加到批处理
targetStmt.addBatch();
count++;
// 执行批处理
if (count % BATCH_SIZE == 0 || count == totalRecords) {
targetStmt.executeBatch();
displayProgress(count, totalRecords, "models 表");
2025-09-29 13:56:36 +08:00
}
}
2025-09-29 17:34:21 +08:00
System.out.println("\n成功转换 models 表数据:" + count + "条记录");
rs.close();
sourceStmt.close();
targetStmt.close();
2025-09-29 13:56:36 +08:00
}
/**
2025-09-29 17:34:21 +08:00
* 显示进度信息
2025-09-29 13:56:36 +08:00
*/
2025-09-29 17:34:21 +08:00
private void displayProgress(int current, int total, String tableName) {
double percentage = (double) current / total * 100;
// 清除当前行并显示进度
System.out.printf("\r%s: 已完成 %.1f%% (%d/%d条)", tableName, percentage, current, total);
}
2025-09-29 13:56:36 +08:00
2025-09-29 17:34:21 +08:00
public static void main(String[] args) {
// 源数据库路径
String sourcePath = "F:\\公司通用模型库.model";
// 目标数据库路径
String targetPath = "F:\\通用模型库.model";
System.out.println("开始数据库转换...");
System.out.println("源数据库: " + sourcePath);
System.out.println("目标数据库: " + targetPath);
long startTime = System.currentTimeMillis();
// 创建转换器并执行转换
SQLiteConverter converter = new SQLiteConverter(sourcePath, targetPath);
converter.convert();
long endTime = System.currentTimeMillis();
double elapsedTime = (endTime - startTime) / 1000.0;
System.out.printf("转换完成、耗时: %.2f秒%n", elapsedTime);
2025-09-29 13:56:36 +08:00
}
}