275 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
		
		
			
		
	
	
			275 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
|   | import java.sql.*;
 | |||
|  | import java.util.UUID;
 | |||
|  | 
 | |||
|  | public class SQLiteConverter {
 | |||
|  |     // SQLite JDBC驱动
 | |||
|  |     private static final String JDBC_DRIVER = "org.sqlite.JDBC";
 | |||
|  | 
 | |||
|  |     // 原始数据库路径
 | |||
|  |     private static final String ORIGINAL_DB_PATH = "jdbc:sqlite:D:\\YJEarth.model";
 | |||
|  | 
 | |||
|  |     // 新数据库路径
 | |||
|  |     private static final String NEW_DB_PATH = "jdbc:sqlite:E:\\通用模型库.model";
 | |||
|  | 
 | |||
|  |     public static void main(String[] args) {
 | |||
|  |         System.out.println("===== 开始数据库转换程序 =====");
 | |||
|  |         System.out.println("原始数据库: " + ORIGINAL_DB_PATH);
 | |||
|  |         System.out.println("目标数据库: " + NEW_DB_PATH + "\n");
 | |||
|  | 
 | |||
|  |         // 使用try-with-resources自动管理连接资源
 | |||
|  |         try (Connection originalConn = DriverManager.getConnection(ORIGINAL_DB_PATH);
 | |||
|  |              Connection newConn = DriverManager.getConnection(NEW_DB_PATH)) {
 | |||
|  | 
 | |||
|  |             System.out.println("✅ 成功连接到原始数据库");
 | |||
|  |             System.out.println("✅ 成功创建并连接到新数据库\n");
 | |||
|  | 
 | |||
|  |             // 在新数据库中创建表结构
 | |||
|  |             System.out.println("===== 开始创建新表结构 =====");
 | |||
|  |             createNewTables(newConn);
 | |||
|  |             System.out.println("===== 新表结构创建完成 =====");
 | |||
|  | 
 | |||
|  |             // 迁移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();
 | |||
|  |     }
 | |||
|  | }
 |