You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Maven项目中如何用Java实现不同数据库不同Schema间的数据迁移

跨Schema数据迁移实现方法
  • 纯SQL脚本迁移:如果两个数据库支持跨库查询,直接编写INSERT INTO ... SELECT语句搭配字段映射、转换逻辑即可,适合表结构差异较小的场景,执行效率最高
  • 现成ETL工具迁移:用DataX、Kettle、Flink CDC等ETL工具,可视化配置字段映射、转换规则,支持全量/增量迁移,无需编码即可完成适配
  • 自定义Java代码迁移:灵活性最高,可支持复杂字段转换、自定义业务校验逻辑,适配所有表结构差异场景,仅需少量编码即可实现

已有验证SQL前提下的纯Java实现步骤

你已经提前完成了SQL逻辑验证,无需重新开发转换规则,按以下步骤实现即可:

1. 配置Maven依赖

在pom.xml中引入两个数据库对应的驱动包,可根据技术选型引入JDBC工具依赖,以下是Spring Boot + Spring JDBC的示例依赖:

<!-- Spring JDBC工具包 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- 数据库A驱动,以MySQL为例,其他数据库替换对应驱动即可 -->
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>
<!-- 数据库B驱动,若与数据库A类型不同单独引入对应驱动 -->

2. 配置双数据源

分别为数据库A(Schema A)、数据库B(Schema B)配置独立数据源,避免操作混淆,Spring Boot下的yaml配置示例:

spring:
  datasource:
    ds-a:
      jdbc-url: jdbc:mysql://{数据库A地址}:{端口}/schema_a?useUnicode=true&characterEncoding=utf8
      username: {数据库A账号}
      password: {数据库A密码}
      driver-class-name: com.mysql.cj.jdbc.Driver
    ds-b:
      jdbc-url: jdbc:mysql://{数据库B地址}:{端口}/schema_b?useUnicode=true&characterEncoding=utf8
      username: {数据库B账号}
      password: {数据库B密码}
      driver-class-name: com.mysql.cj.jdbc.Driver

配置完成后分别初始化对应数据源的JdbcTemplate实例,分别负责两个库的读写操作。

3. 核心迁移逻辑实现

迁移时采用分批读写的方案,避免一次性拉取全量数据撑爆内存,示例代码如下:

// 已分别注入对应两个库的JdbcTemplate实例:jdbcTemplateA(读库A)、jdbcTemplateB(写库B)
// 你已经验证完成的查询转换SQL,带分页参数
String readSql = "SELECT 转换后字段1,转换后字段2,... FROM 源表 WHERE 过滤条件 LIMIT ?,?";
// 目标表插入SQL
String writeSql = "INSERT INTO 目标表(字段1,字段2,...) VALUES (?,?,...)";

int batchSize = 1000;
long offset = 0;
while (true) {
    // 从库A分批读取转换后的数据
    List<Map<String, Object>> batchData = jdbcTemplateA.queryForList(readSql, offset, batchSize);
    if (batchData.isEmpty()) {
        break;
    }
    // 开启事务批量写入库B
    jdbcTemplateB.execute((ConnectionCallback<Void>) conn -> {
        conn.setAutoCommit(false);
        try (PreparedStatement ps = conn.prepareStatement(writeSql)) {
            for (Map<String, Object> row : batchData) {
                ps.setObject(1, row.get("转换后字段1"));
                ps.setObject(2, row.get("转换后字段2"));
                // 其余字段按顺序赋值
                ps.addBatch();
            }
            ps.executeBatch();
            conn.commit();
        } catch (Exception e) {
            conn.rollback();
            throw new RuntimeException("批次迁移失败,已回滚", e);
        }
        return null;
    });
    offset += batchSize;
}

如果不使用Spring框架,用原生JDBC实现逻辑完全一致,仅需自行管理两个数据源的连接、Statement资源即可。

4. 数据校验与异常兼容

  • 迁移前给目标表添加唯一索引,避免重复写入脏数据
  • 迁移过程中记录已完成的主键/偏移量范围,出现异常中断后可直接从断点续跑,无需全量重跑
  • 迁移完成后做数据一致性校验:对比两边表的记录数、核心字段的sum值、抽样数据字段内容,确保迁移完全正确

内容的提问来源于stack exchange,提问作者Satya Ram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 17:54:08