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
相关产品推荐
相关产品推荐

