parent
8191d181e8
commit
aa2907fc7a
@ -1,272 +0,0 @@
|
|||||||
package Tools;
|
|
||||||
|
|
||||||
import java.sql.*;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class DatabaseSynchronizer {
|
|
||||||
// 数据库连接配置
|
|
||||||
private static final String SQLITE_URL = "jdbc:sqlite:D:\\dsWork\\CcsEduData\\数据库与脚本\\edudb_gather_220100000000_full_fullreport.db";
|
|
||||||
private static final String PG_URL = "jdbc:postgresql://10.10.14.71:5432/szjz_db";
|
|
||||||
private static final String PG_USER = "postgres";
|
|
||||||
private static final String PG_PASSWORD = "DsideaL147258369";
|
|
||||||
|
|
||||||
public void syncDatabase() {
|
|
||||||
// 要同步的表名列表
|
|
||||||
//List<String> tables = List.of("教基1001", "教基4149", "教基3115", "教基2107","教基2106");
|
|
||||||
List<String> tables = List.of("教基3113");
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 加载数据库驱动
|
|
||||||
Class.forName("org.sqlite.JDBC");
|
|
||||||
Class.forName("org.postgresql.Driver");
|
|
||||||
|
|
||||||
// 同步每个表
|
|
||||||
for (String tableName : tables) {
|
|
||||||
syncTable(tableName);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void syncTable(String tableName) throws SQLException {
|
|
||||||
// 获取表结构和数据
|
|
||||||
TableInfo tableInfo = getTableInfo(tableName);
|
|
||||||
List<List<Object>> data = getTableData(tableName);
|
|
||||||
|
|
||||||
// 在PostgreSQL中创建表并插入数据
|
|
||||||
createTableInPostgres(tableInfo);
|
|
||||||
insertDataToPostgres(tableInfo, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TableInfo getTableInfo(String tableName) throws SQLException {
|
|
||||||
TableInfo tableInfo = new TableInfo(tableName);
|
|
||||||
|
|
||||||
try (Connection conn = DriverManager.getConnection(SQLITE_URL);
|
|
||||||
ResultSet rs = conn.getMetaData().getColumns(null, null, tableName, null)) {
|
|
||||||
|
|
||||||
while (rs.next()) {
|
|
||||||
String columnName = rs.getString("COLUMN_NAME");
|
|
||||||
String sqliteType = rs.getString("TYPE_NAME");
|
|
||||||
// 转换SQLite类型到PostgreSQL类型
|
|
||||||
String pgType = convertSqliteTypeToPg(sqliteType);
|
|
||||||
tableInfo.addColumn(columnName, pgType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tableInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void createTableInPostgres(TableInfo tableInfo) throws SQLException {
|
|
||||||
StringBuilder createTableSQL = new StringBuilder();
|
|
||||||
createTableSQL.append("CREATE TABLE IF NOT EXISTS ")
|
|
||||||
.append(tableInfo.tableName)
|
|
||||||
.append(" (");
|
|
||||||
|
|
||||||
for (int i = 0; i < tableInfo.columnNames.size(); i++) {
|
|
||||||
if (i > 0) createTableSQL.append(", ");
|
|
||||||
createTableSQL.append(tableInfo.columnNames.get(i))
|
|
||||||
.append(" ")
|
|
||||||
.append(tableInfo.columnTypes.get(i));
|
|
||||||
}
|
|
||||||
createTableSQL.append(")");
|
|
||||||
|
|
||||||
try (Connection conn = DriverManager.getConnection(PG_URL, PG_USER, PG_PASSWORD);
|
|
||||||
Statement stmt = conn.createStatement()) {
|
|
||||||
stmt.execute(createTableSQL.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void insertDataToPostgres(TableInfo tableInfo, List<List<Object>> data) throws SQLException {
|
|
||||||
if (data.isEmpty()) {
|
|
||||||
System.out.println("没有数据需要插入");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try (Connection conn = DriverManager.getConnection(PG_URL, PG_USER, PG_PASSWORD)) {
|
|
||||||
conn.setAutoCommit(false);
|
|
||||||
|
|
||||||
StringBuilder insertSQL = new StringBuilder();
|
|
||||||
insertSQL.append("INSERT INTO ")
|
|
||||||
.append(tableInfo.tableName)
|
|
||||||
.append(" (");
|
|
||||||
|
|
||||||
for (int i = 0; i < tableInfo.columnNames.size(); i++) {
|
|
||||||
if (i > 0) insertSQL.append(", ");
|
|
||||||
insertSQL.append(tableInfo.columnNames.get(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
insertSQL.append(") VALUES (");
|
|
||||||
|
|
||||||
for (int i = 0; i < tableInfo.columnNames.size(); i++) {
|
|
||||||
if (i > 0) insertSQL.append(", ");
|
|
||||||
insertSQL.append("?");
|
|
||||||
}
|
|
||||||
|
|
||||||
insertSQL.append(")");
|
|
||||||
|
|
||||||
System.out.println("插入SQL: " + insertSQL);
|
|
||||||
|
|
||||||
try (PreparedStatement pstmt = conn.prepareStatement(insertSQL.toString())) {
|
|
||||||
int batchSize = 1000;
|
|
||||||
int count = 0;
|
|
||||||
int totalInserted = 0;
|
|
||||||
|
|
||||||
for (List<Object> row : data) {
|
|
||||||
if (row.size() != tableInfo.columnNames.size()) {
|
|
||||||
System.out.println("警告: 数据行列数不匹配");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < row.size(); i++) {
|
|
||||||
Object value = row.get(i);
|
|
||||||
String columnType = tableInfo.columnTypes.get(i).toUpperCase();
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (value == null) {
|
|
||||||
pstmt.setNull(i + 1, Types.NULL);
|
|
||||||
}
|
|
||||||
// 处理数值类型
|
|
||||||
else if (columnType.contains("DOUBLE") || columnType.contains("NUMERIC") ||
|
|
||||||
columnType.contains("DECIMAL") || columnType.contains("REAL")) {
|
|
||||||
if (value instanceof String) {
|
|
||||||
String strValue = (String) value;
|
|
||||||
if (strValue.isEmpty()) {
|
|
||||||
pstmt.setNull(i + 1, Types.DOUBLE);
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
pstmt.setDouble(i + 1, Double.parseDouble(strValue));
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
pstmt.setNull(i + 1, Types.DOUBLE);
|
|
||||||
System.out.println("警告: 无法转换为数值类型: " + strValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (value instanceof Number) {
|
|
||||||
pstmt.setDouble(i + 1, ((Number) value).doubleValue());
|
|
||||||
} else {
|
|
||||||
pstmt.setNull(i + 1, Types.DOUBLE);
|
|
||||||
System.out.println("警告: 未知的数值类型: " + value.getClass());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 处理整数类型
|
|
||||||
else if (columnType.contains("INTEGER") || columnType.contains("INT")) {
|
|
||||||
if (value instanceof String) {
|
|
||||||
String strValue = (String) value;
|
|
||||||
if (strValue.isEmpty()) {
|
|
||||||
pstmt.setNull(i + 1, Types.INTEGER);
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
pstmt.setInt(i + 1, Integer.parseInt(strValue));
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
pstmt.setNull(i + 1, Types.INTEGER);
|
|
||||||
System.out.println("警告: 无法转换为整数类型: " + strValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (value instanceof Number) {
|
|
||||||
pstmt.setInt(i + 1, ((Number) value).intValue());
|
|
||||||
} else {
|
|
||||||
pstmt.setNull(i + 1, Types.INTEGER);
|
|
||||||
System.out.println("警告: 未知的整数类型: " + value.getClass());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 其他类型当作字符串处理
|
|
||||||
else {
|
|
||||||
pstmt.setString(i + 1, value.toString());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("警告: 设置值时出错: 列=" + tableInfo.columnNames.get(i) +
|
|
||||||
", 值=" + value + ", 类型=" + columnType);
|
|
||||||
pstmt.setNull(i + 1, Types.NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pstmt.addBatch();
|
|
||||||
|
|
||||||
if (++count % batchSize == 0) {
|
|
||||||
pstmt.executeBatch();
|
|
||||||
conn.commit();
|
|
||||||
totalInserted += count;
|
|
||||||
count = 0;
|
|
||||||
System.out.println("已插入 " + totalInserted + " 行");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count > 0) {
|
|
||||||
pstmt.executeBatch();
|
|
||||||
conn.commit();
|
|
||||||
totalInserted += count;
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println("总共插入 " + totalInserted + " 行数据");
|
|
||||||
} catch (SQLException e) {
|
|
||||||
conn.rollback();
|
|
||||||
System.out.println("插入数据时出错: " + e.getMessage());
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改 getTableData 方法,添加调试信息
|
|
||||||
private List<List<Object>> getTableData(String tableName) throws SQLException {
|
|
||||||
List<List<Object>> data = new ArrayList<>();
|
|
||||||
|
|
||||||
try (Connection conn = DriverManager.getConnection(SQLITE_URL);
|
|
||||||
Statement stmt = conn.createStatement();
|
|
||||||
ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName)) {
|
|
||||||
|
|
||||||
ResultSetMetaData metaData = rs.getMetaData();
|
|
||||||
int columnCount = metaData.getColumnCount();
|
|
||||||
|
|
||||||
System.out.println("Table: " + tableName + ", Column count: " + columnCount);
|
|
||||||
for (int i = 1; i <= columnCount; i++) {
|
|
||||||
System.out.println("Column " + i + ": " + metaData.getColumnName(i) +
|
|
||||||
" (" + metaData.getColumnTypeName(i) + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
while (rs.next()) {
|
|
||||||
List<Object> row = new ArrayList<>();
|
|
||||||
for (int i = 1; i <= columnCount; i++) {
|
|
||||||
row.add(rs.getObject(i));
|
|
||||||
}
|
|
||||||
data.add(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println("Read " + data.size() + " rows from SQLite");
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String convertSqliteTypeToPg(String sqliteType) {
|
|
||||||
// 类型转换映射
|
|
||||||
return switch (sqliteType.toUpperCase()) {
|
|
||||||
case "INTEGER" -> "INTEGER";
|
|
||||||
case "REAL" -> "DOUBLE PRECISION";
|
|
||||||
case "TEXT" -> "TEXT";
|
|
||||||
case "BLOB" -> "BYTEA";
|
|
||||||
default -> "TEXT";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 表信息存储类
|
|
||||||
private static class TableInfo {
|
|
||||||
String tableName;
|
|
||||||
List<String> columnNames = new ArrayList<>();
|
|
||||||
List<String> columnTypes = new ArrayList<>();
|
|
||||||
|
|
||||||
TableInfo(String tableName) {
|
|
||||||
this.tableName = tableName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addColumn(String name, String type) {
|
|
||||||
columnNames.add(name);
|
|
||||||
columnTypes.add(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
DatabaseSynchronizer synchronizer = new DatabaseSynchronizer();
|
|
||||||
synchronizer.syncDatabase();
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in new issue