需求:实现MySQL数据库的数据同步更新到瀚高数据库
问题点:一些第三方的数据库迁移工具只能做迁移不能做数据同步,所以要使用Java来实现
新建项目之后注意一定要导入这个依赖
<dependency>
<groupId>com.highgo</groupId>
<artifactId>HgdbJdbc</artifactId>
<version>6.2.2</version>
</dependency>
具体实现代码
@Slf4j
public class DataSyncTask {
private static final String MYSQL_URL = "jdbc:mysql://000.000.000.000:000/yourtable?tinyInt1isBit=false";
private static final String MYSQL_USER = "root";
private static final String MYSQL_PASSWORD = "123456";
private static final String HIGHGO_URL = "jdbc:highgo://000.000.000.000:6000/yourtable";
private static final String HIGHGO_USER = "xxx";
private static final String HIGHGO_PASSWORD = "xxx";
private static final List<String> MYSQL_TABLES = new ArrayList<>();
static {
MYSQL_TABLES.add("yourtable");
}
//对于数据量较大的情况,通常建议采用 批量插入优化 和 多线程处理 的组合方案
public static void main(String[] args) {
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
// 每隔十分钟执行一次同步任务
scheduler.scheduleAtFixedRate(() -> {
syncDataFromMySQLToHighgo();
}, 0, 10, TimeUnit.MINUTES);
// 停止定时任务
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
scheduler.shutdown();
}));
}
private static void syncDataFromMySQLToHighgo() {
try (Connection mysqlConn = DriverManager.getConnection(MYSQL_URL, MYSQL_USER, MYSQL_PASSWORD);
Connection highgoConn = DriverManager.getConnection(HIGHGO_URL, HIGHGO_USER, HIGHGO_PASSWORD)) {
for (String tableName : MYSQL_TABLES) {
syncTableData(mysqlConn, highgoConn, tableName);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
private static void syncTableData(Connection mysqlConn, Connection highgoConn, String tableName) throws SQLException {
// 从HighGo读取已存在的ID
Set<Integer> existingIds = new HashSet<>();
String checkExistingSql = "SELECT id FROM " + tableName + " WHERE date >= NOW() - INTERVAL 30 MINUTE";
// String checkExistingSql = "SELECT id FROM " + tableName + " WHERE date < '2024-01-29'";
try (PreparedStatement checkStmt = highgoConn.prepareStatement(checkExistingSql);
ResultSet rsExisting = checkStmt.executeQuery()) {
while (rsExisting.next()) {
existingIds.add(rsExisting.getInt(1)); // 假设id是整型
}
}
// 从MySQL读取数据
String selectSql = "SELECT * FROM " + tableName + " WHERE date >= NOW() - INTERVAL 30 MINUTE";
try (PreparedStatement selectStmt = mysqlConn.prepareStatement(selectSql);
ResultSet resultSet = selectStmt.executeQuery()) {
// 准备插入语句
String insertSql = "INSERT INTO " + tableName + " (";
StringBuilder columns = new StringBuilder();
StringBuilder placeholders = new StringBuilder();
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
if (i > 1) {
columns.append(", ");
placeholders.append(", ");
}
columns.append(metaData.getColumnName(i));
placeholders.append("?");
}
insertSql += columns.toString() + ") VALUES (" + placeholders.toString() + ")";
try (PreparedStatement insertStmt = highgoConn.prepareStatement(insertSql)) {
while (resultSet.next()) {
int id = resultSet.getInt("id");
if (!existingIds.contains(id)) {
for (int i = 1; i <= columnCount; i++) {
insertStmt.setObject(i, resultSet.getObject(i));
}
insertStmt.addBatch();
}
}
insertStmt.executeBatch(); // 执行批量插入
}
}
}
}
数据同步思路
- 连接MySQL
- 连接HighGo
- 查询MySQL 30分钟前数据,HighGo中查询30分钟前的数据,对比数据,如果数据不一致,则存储到集合。
- 需要写MySQL查询语句
- 需要写highgo查询语句
- 需要写插入highgo语句
- 调用批量执行方法,一次提交commit
- 定时任务:使用单线程定时器每隔十分钟执行一次数据同步任务。
- 关闭连接
注意:
在 MySQL 中,tinyint(1) 经常用于表示布尔值,其中 1 对应 true,0 对应 false。如果你的数据库表中 tinyint 存储的是 99,而 JDBC 驱动默认将 1 映射为 true,那么这可能是驱动的一个默认行为。
如果数据库中的 tinyint(1) 类型通常被 JDBC 驱动映射为 Java 中的 boolean 类型,那么当该字段存储的是 1 或者 true 时,resultSet.getObject(i) 返回的就是 true。