Jfinal+SQLite解决MYSQL迁移表未复制索引困难,完善迁移工具

原mysql 表查询存在索引,

查询sql含force index(字段),SQLite不支持,会报错

解决办法,要么删除索引,要么强制执行索引 换成 INDEXED BY, 

String select sql="select * ";

String fromSql=" from tableName force index (START_TIME_TYPE) where 1=1

if (fromSql.contains("force index")){
   fromSql= fromSql.replaceAll("(?i)\\bFROM\\s+(\\w+)(\\s+\\w+)?\\s+force\\s+index\\s*\\(\\s*(\\w+)\\s*\\)",
         "FROM $1 $2 INDEXED BY $3");
}

这里就需要给sqlite数据库表添加对应索引,不然会报错SQLiteException: no such index: START_TIME_TYPE

生产数据库中,表多,索引比较多,在原先迁移表工具添加索引迁移,暂时未发现问题,需多多测试

package changeDataBase;
import java.sql.*;
import java.util.*;
public class MySQLToSQLiteMigration {
    private static final String MYSQL_URL = "jdbc:mysql://localhost:3306/database";
    private static final String MYSQL_USER = "admin";
    private static final String MYSQL_PASSWORD = "123456";
    private static final String SQLITE_URL = "jdbc:sqlite:D:/database/database.sqlite";
    public static void main(String[] args) {
        try {
            Class.forName("org.sqlite.JDBC");
        } catch (ClassNotFoundException var2) {
            System.err.println("SQLite JDBC driver not found!");
            var2.printStackTrace();
            return;
        }
        List tableNames = getTableNamesFromMySQL();
        migrateTablesToSQLite(tableNames);
    }
    private static List getTableNamesFromMySQL() {
        ArrayList tableNames = new ArrayList<>();
        try (Connection conn = DriverManager.getConnection(MYSQL_URL, MYSQL_USER, MYSQL_PASSWORD)) {
            DatabaseMetaData metaData = conn.getMetaData();
            ResultSet rs = metaData.getTables(null, null, "%", new String[]{"TABLE"});
            while (rs.next()) {
                tableNames.add(rs.getString("TABLE_NAME"));
            }
        } catch (SQLException var6) {
            var6.printStackTrace();
        }
        return tableNames;
    }
    private static void migrateTablesToSQLite(List tableNames) {
        try (Connection mysqlConn = DriverManager.getConnection(MYSQL_URL, MYSQL_USER, MYSQL_PASSWORD);
             Connection sqliteConn = DriverManager.getConnection(SQLITE_URL)) {
            Iterator var3 = tableNames.iterator();
            while (var3.hasNext()) {
                String tableName = var3.next();
                System.out.println("Migrating table: " + tableName);
                migrateTable(mysqlConn, sqliteConn, tableName);
            }
        } catch (SQLException var9) {
            var9.printStackTrace();
        }
    }
    private static void migrateTable(Connection mysqlConn, Connection sqliteConn, String tableName) throws SQLException {
        String selectSql = "SELECT * FROM " + tableName;
        try (Statement stmt = mysqlConn.createStatement();
             ResultSet rs = stmt.executeQuery(selectSql)) {
            String createTableSql = getCreateTableSql(mysqlConn, tableName);
            try (Statement sqliteStmt = sqliteConn.createStatement()) {
                sqliteStmt.execute(createTableSql);
            }
            String insertSql = getInsertSql(rs.getMetaData(), tableName);
            try (PreparedStatement sqlitePstmt = sqliteConn.prepareStatement(insertSql)) {
                while (rs.next()) {
                    for (int i = 1; i  columns = new ArrayList<>();
        String primaryKey = null;
        while (rs.next()) {
            String columnName = rs.getString("COLUMN_NAME");
            String columnType = getSQLiteType(rs.getString("TYPE_NAME"));
            columns.add(columnName + " " + columnType);
        }
        // 获取主键信息
        String primaryKeySql = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? AND CONSTRAINT_NAME = 'PRIMARY'";
        try (PreparedStatement pstmt = mysqlConn.prepareStatement(primaryKeySql)) {
            pstmt.setString(1, "database");
            pstmt.setString(2, tableName);
            try (ResultSet pkRs = pstmt.executeQuery()) {
                if (pkRs.next()) {
                    primaryKey = pkRs.getString("COLUMN_NAME");
                }
            }
        }
        sb.append(String.join(", ", columns));
        if (primaryKey != null) {
            sb.append(", PRIMARY KEY (").append(primaryKey).append(")");
        }
        sb.append(");");
        return sb.toString();
    }
    private static String getInsertSql(ResultSetMetaData metaData, String tableName) throws SQLException {
        StringBuilder sb = new StringBuilder("INSERT INTO ").append(tableName).append(" (");
        for (int i = 1; i
        Map> indexMap = new LinkedHashMap<>();
        try (PreparedStatement ps = mysqlConn.prepareStatement(sql)) {
            ps.setString(1, tableName);
            try (ResultSet rs = ps.executeQuery()) {
                while (rs.next()) {
                    String idxName = rs.getString("INDEX_NAME");
                    indexMap.computeIfAbsent(idxName, k -> new ArrayList<>())
                            .add("\"" + rs.getString("COLUMN_NAME") + "\"");
                }
            }
        }
        // 2. 逐个在 SQLite 建索引
        for (Map.Entry> e : indexMap.entrySet()) {
            String cols = String.join(", ", e.getValue());
            // 索引名在 SQLite 中保持同名,避免冲突可加前缀
            String createIdx = String.format(
                    "CREATE %s INDEX IF NOT EXISTS \"%s\" ON \"%s\" (%s);",
                    e.getKey().toUpperCase().startsWith("UNIQUE") ? "UNIQUE" : "",
                    e.getKey(), tableName, cols);
            try (Statement st = sqliteConn.createStatement()) {
                st.execute(createIdx);
                System.out.println("    " + createIdx.trim());
            }
        }
    }
}
posted @ 2025-07-24 22:32  yfceshi  阅读(9)  评论(0)    收藏  举报