模型库、矢量文件
This commit is contained in:
@ -1,274 +1,249 @@
|
||||
package com.yj.earth.common.util;
|
||||
|
||||
import cn.hutool.core.lang.UUID;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.UUID;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SQLiteConverter {
|
||||
// SQLite JDBC驱动
|
||||
private static final String JDBC_DRIVER = "org.sqlite.JDBC";
|
||||
// 源数据库和目标数据库路径
|
||||
private String sourceDbPath;
|
||||
private String targetDbPath;
|
||||
// 批处理大小、可根据内存情况调整
|
||||
private static final int BATCH_SIZE = 100;
|
||||
|
||||
// 原始数据库路径
|
||||
private static final String ORIGINAL_DB_PATH = "jdbc:sqlite:D:\\YJEarth.model";
|
||||
public SQLiteConverter(String sourceDbPath, String targetDbPath) {
|
||||
this.sourceDbPath = sourceDbPath;
|
||||
this.targetDbPath = targetDbPath;
|
||||
}
|
||||
|
||||
// 新数据库路径
|
||||
private static final String NEW_DB_PATH = "jdbc:sqlite:E:\\通用模型库.model";
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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("目标表结构创建完成");
|
||||
}
|
||||
|
||||
/**
|
||||
* 为 model 表的每个字段创建索引
|
||||
*/
|
||||
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表索引创建完成");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 表");
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("\n成功转换 mode_types 表数据:" + count + "条记录");
|
||||
rs.close();
|
||||
sourceStmt.close();
|
||||
targetStmt.close();
|
||||
}
|
||||
|
||||
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 表");
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("\n成功转换 models 表数据:" + count + "条记录");
|
||||
rs.close();
|
||||
sourceStmt.close();
|
||||
targetStmt.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示进度信息
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("===== 开始数据库转换程序 =====");
|
||||
System.out.println("原始数据库: " + ORIGINAL_DB_PATH);
|
||||
System.out.println("目标数据库: " + NEW_DB_PATH + "\n");
|
||||
// 源数据库路径
|
||||
String sourcePath = "F:\\公司通用模型库.model";
|
||||
// 目标数据库路径
|
||||
String targetPath = "F:\\通用模型库.model";
|
||||
|
||||
// 使用try-with-resources自动管理连接资源
|
||||
try (Connection originalConn = DriverManager.getConnection(ORIGINAL_DB_PATH);
|
||||
Connection newConn = DriverManager.getConnection(NEW_DB_PATH)) {
|
||||
System.out.println("开始数据库转换...");
|
||||
System.out.println("源数据库: " + sourcePath);
|
||||
System.out.println("目标数据库: " + targetPath);
|
||||
|
||||
System.out.println("✅ 成功连接到原始数据库");
|
||||
System.out.println("✅ 成功创建并连接到新数据库\n");
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// 在新数据库中创建表结构
|
||||
System.out.println("===== 开始创建新表结构 =====");
|
||||
createNewTables(newConn);
|
||||
System.out.println("===== 新表结构创建完成 =====");
|
||||
// 创建转换器并执行转换
|
||||
SQLiteConverter converter = new SQLiteConverter(sourcePath, targetPath);
|
||||
converter.convert();
|
||||
|
||||
// 迁移mode_types表数据到model_type表
|
||||
System.out.println("\n===== 开始迁移mode_types表数据 =====");
|
||||
MigrationResult modeTypesResult = migrateModeTypes(originalConn, newConn);
|
||||
System.out.println("===== mode_types表数据迁移完成 =====");
|
||||
System.out.printf(" 成功: %d 条, 失败: %d 条, 总计: %d 条%n",
|
||||
modeTypesResult.successCount,
|
||||
modeTypesResult.failureCount,
|
||||
modeTypesResult.totalCount);
|
||||
|
||||
// 迁移models表数据到model表
|
||||
System.out.println("\n===== 开始迁移models表数据 =====");
|
||||
MigrationResult modelsResult = migrateModels(originalConn, newConn);
|
||||
System.out.println("===== models表数据迁移完成 =====");
|
||||
System.out.printf(" 成功: %d 条, 失败: %d 条, 总计: %d 条%n",
|
||||
modelsResult.successCount,
|
||||
modelsResult.failureCount,
|
||||
modelsResult.totalCount);
|
||||
|
||||
if (modeTypesResult.failureCount > 0 || modelsResult.failureCount > 0) {
|
||||
System.out.println("\n⚠️ 注意:部分记录迁移失败、已跳过错误记录");
|
||||
}
|
||||
|
||||
System.out.println("\n===== 数据库转换处理完成! =====");
|
||||
|
||||
} catch (SQLException e) {
|
||||
System.err.println("\n❌ 数据库连接错误: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 迁移结果数据类
|
||||
*/
|
||||
private static class MigrationResult {
|
||||
int successCount;
|
||||
int failureCount;
|
||||
int totalCount;
|
||||
|
||||
MigrationResult(int success, int failure, int total) {
|
||||
this.successCount = success;
|
||||
this.failureCount = failure;
|
||||
this.totalCount = total;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在新数据库中创建表结构
|
||||
*/
|
||||
private static void createNewTables(Connection conn) throws SQLException {
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
// 创建model_type表
|
||||
System.out.println("正在创建model_type表...");
|
||||
String createModelTypeTable = "CREATE TABLE IF NOT EXISTS \"model_type\" (" +
|
||||
"\"id\" TEXT," +
|
||||
"\"name\" TEXT," +
|
||||
"\"parent_id\" TEXT," +
|
||||
"\"tree_index\" INTEGER," +
|
||||
"\"created_at\" TEXT," +
|
||||
"\"updated_at\" TEXT," +
|
||||
"PRIMARY KEY (\"id\")" +
|
||||
");";
|
||||
stmt.execute(createModelTypeTable);
|
||||
System.out.println("✅ model_type表创建完成");
|
||||
|
||||
// 创建model表
|
||||
System.out.println("正在创建model表...");
|
||||
String createModelTable = "CREATE TABLE IF NOT EXISTS \"model\" (" +
|
||||
"\"id\" TEXT," +
|
||||
"\"model_type_id\" TEXT," +
|
||||
"\"model_name\" TEXT," +
|
||||
"\"model_type\" TEXT," +
|
||||
"\"poster_type\" TEXT," +
|
||||
"\"poster\" TEXT," +
|
||||
"\"data\" TEXT," +
|
||||
"\"data_bytes\" BLOB," +
|
||||
"\"view\" TEXT," +
|
||||
"\"created_at\" TEXT," +
|
||||
"\"updated_at\" TEXT," +
|
||||
"PRIMARY KEY (\"id\")" +
|
||||
");";
|
||||
stmt.execute(createModelTable);
|
||||
System.out.println("✅ model表创建完成");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 迁移mode_types表数据到model_type表
|
||||
*/
|
||||
private static MigrationResult migrateModeTypes(Connection originalConn, Connection newConn) throws SQLException {
|
||||
// 先获取记录总数、用于显示进度
|
||||
int totalCount;
|
||||
try (PreparedStatement countStmt = originalConn.prepareStatement("SELECT COUNT(*) FROM mode_types");
|
||||
ResultSet countRs = countStmt.executeQuery()) {
|
||||
countRs.next();
|
||||
totalCount = countRs.getInt(1);
|
||||
System.out.println("发现 " + totalCount + " 条mode_types记录待迁移");
|
||||
}
|
||||
|
||||
// 查询原始表数据
|
||||
try (PreparedStatement selectStmt = originalConn.prepareStatement("SELECT * FROM mode_types");
|
||||
ResultSet rs = selectStmt.executeQuery()) {
|
||||
|
||||
// 插入到新表、关闭自动提交以提高性能
|
||||
newConn.setAutoCommit(false);
|
||||
|
||||
try (PreparedStatement insertStmt = newConn.prepareStatement(
|
||||
"INSERT INTO model_type (" +
|
||||
"id, name, parent_id, tree_index, created_at, updated_at" +
|
||||
") VALUES (?, ?, ?, ?, ?, ?)")) {
|
||||
|
||||
int successCount = 0;
|
||||
int failureCount = 0;
|
||||
|
||||
while (rs.next()) {
|
||||
try {
|
||||
// 生成新的UUID作为ID
|
||||
String newId = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
String typeName = rs.getString("type_name");
|
||||
|
||||
// 映射字段
|
||||
insertStmt.setString(1, newId);
|
||||
insertStmt.setString(2, typeName);
|
||||
insertStmt.setString(3, rs.getString("p_id"));
|
||||
insertStmt.setInt(4, 0);
|
||||
insertStmt.setString(5, rs.getString("created_at"));
|
||||
insertStmt.setString(6, rs.getString("updated_at"));
|
||||
|
||||
insertStmt.executeUpdate();
|
||||
successCount++;
|
||||
|
||||
// 每迁移10条记录或最后一批记录时打印进度
|
||||
if (successCount % 10 == 0 || (successCount + failureCount) == totalCount) {
|
||||
printProgress(successCount + failureCount, totalCount);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
// 捕获单条记录的异常、跳过该记录
|
||||
failureCount++;
|
||||
System.err.printf("\n❌ 迁移mode_types记录失败 (序号: %d): %s%n",
|
||||
successCount + failureCount, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
newConn.commit();
|
||||
return new MigrationResult(successCount, failureCount, totalCount);
|
||||
} catch (SQLException e) {
|
||||
newConn.rollback();
|
||||
throw e;
|
||||
} finally {
|
||||
newConn.setAutoCommit(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 迁移models表数据到model表
|
||||
*/
|
||||
private static MigrationResult migrateModels(Connection originalConn, Connection newConn) throws SQLException {
|
||||
// 先获取记录总数、用于显示进度
|
||||
int totalCount;
|
||||
try (PreparedStatement countStmt = originalConn.prepareStatement("SELECT COUNT(*) FROM models");
|
||||
ResultSet countRs = countStmt.executeQuery()) {
|
||||
countRs.next();
|
||||
totalCount = countRs.getInt(1);
|
||||
System.out.println("发现 " + totalCount + " 条models记录待迁移");
|
||||
}
|
||||
|
||||
// 查询原始表数据
|
||||
try (PreparedStatement selectStmt = originalConn.prepareStatement("SELECT * FROM models");
|
||||
ResultSet rs = selectStmt.executeQuery()) {
|
||||
|
||||
// 插入到新表、关闭自动提交以提高性能
|
||||
newConn.setAutoCommit(false);
|
||||
|
||||
try (PreparedStatement insertStmt = newConn.prepareStatement(
|
||||
"INSERT INTO model (" +
|
||||
"id, model_type_id, model_name, model_type, poster_type, " +
|
||||
"poster, data, data_bytes, view, created_at, updated_at" +
|
||||
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) {
|
||||
|
||||
int successCount = 0;
|
||||
int failureCount = 0;
|
||||
|
||||
while (rs.next()) {
|
||||
try {
|
||||
// 生成新的UUID作为ID
|
||||
String newId = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
String modelName = rs.getString("model_name");
|
||||
|
||||
// 映射字段
|
||||
insertStmt.setString(1, newId);
|
||||
insertStmt.setString(2, rs.getString("p_id"));
|
||||
insertStmt.setString(3, modelName);
|
||||
insertStmt.setString(4, rs.getString("model_type"));
|
||||
insertStmt.setString(5, rs.getString("poster_type"));
|
||||
|
||||
// 处理BLOB字段
|
||||
byte[] posterBlob = rs.getBytes("poster");
|
||||
insertStmt.setString(6, posterBlob != null ? new String(posterBlob) : null);
|
||||
insertStmt.setString(7, null);
|
||||
|
||||
byte[] dataBlob = rs.getBytes("data");
|
||||
insertStmt.setBytes(8, dataBlob);
|
||||
insertStmt.setString(9, null);
|
||||
|
||||
insertStmt.setString(10, rs.getString("created_at"));
|
||||
insertStmt.setString(11, rs.getString("updated_at"));
|
||||
|
||||
insertStmt.executeUpdate();
|
||||
successCount++;
|
||||
|
||||
// 每迁移10条记录或最后一批记录时打印进度
|
||||
if (successCount % 10 == 0 || (successCount + failureCount) == totalCount) {
|
||||
printProgress(successCount + failureCount, totalCount);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
// 捕获单条记录的异常、跳过该记录
|
||||
failureCount++;
|
||||
System.err.printf("\n❌ 迁移models记录失败 (序号: %d, 名称: %s): %s%n",
|
||||
successCount + failureCount,
|
||||
rs.getString("model_name"),
|
||||
e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
newConn.commit();
|
||||
return new MigrationResult(successCount, failureCount, totalCount);
|
||||
} catch (SQLException e) {
|
||||
newConn.rollback();
|
||||
throw e;
|
||||
} finally {
|
||||
newConn.setAutoCommit(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印迁移进度
|
||||
*/
|
||||
private static void printProgress(int current, int total) {
|
||||
double percentage = (current * 100.0) / total;
|
||||
System.out.printf("迁移进度: %d/%d (%.1f%%)\r", current, total, percentage);
|
||||
System.out.flush();
|
||||
long endTime = System.currentTimeMillis();
|
||||
double elapsedTime = (endTime - startTime) / 1000.0;
|
||||
System.out.printf("转换完成、耗时: %.2f秒%n", elapsedTime);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user