parent
7405a02aad
commit
75ad55318c
@ -0,0 +1,271 @@
|
|||||||
|
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");
|
||||||
|
|
||||||
|
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