Java代码实现两个数据库之间的数据同步

需求背景

有A&B两个数据库,以A为主,B要同步A上的数据,同步涉及数据的增删改查,且要每天同步一次。条件限制是,只能调用中台提供的接口操作数据库,不能写SQL。

解决思路

由于只能通过中台调用接口操作数据库,所以解决方法被限制在后端代码层面。至于每天执行一次,使用SpringBoot的定时任务注解@Scheduled就可以了。

1、遍历遍历再遍历

对于增加和修改,将A库中所有的数据通过接口拿到一个List里面,遍历这个List,每一趟检查B库中是否存在主键对应的数据,如果存在,则将数据更新,如果不存在,则直接插入。
对于A库中删除的数据,需要反向遍历,即将B库的数据拿出来,将数据进行遍历对比,如果发现B库中有的数据而A库中没有,则删除B库中的数据。

2、B中数据全删了,把A中的数据写上

如题,通过中台拿到A中的数据,然后把B库清空,再写A库的数据。
逻辑十分简单

3、内存中对比变化,只把变化落盘到数据库

大致思路是通过数据中台拿到A库的List和B库的List,比对这两个List的差别,只把差别写到数据库。
将A库中的数据拿到newList中,B库中的数据拿到oldList中,对newList进行遍历,每次遍历都寻找oldList中是否存在与newList对应的数据(通过主键作为对应标识);如果存在,则判断两个对象是否相等(要重写equals()和hashcode()方法),相等则直接从两个队列中剔除这个数据,不相等则调用接口进行数据更新,更新完了之后将更新过的数据从两个List中剔除;这样遍历完了之后,newList中剩下的没被剔除的数据就是B库需要新增的数据,oldList中剩下的没被剔除的数据就是B库需要删除的数据,需要修改的数据在遍历过程中已完成修改。
这个方案的伪码如下:

//A库中的数据同步到B库伪码

//A库中的数据拿到newList中,B库中的数据拿到oldList
List<Data> newDataList;
List<Data> oldDataList;

//从数据库中取数据......

//开始遍历比对
for (Data newData : newDataList) {
	for (Data oldData : oldDataList) {
		//通过主键判断oldData与newData是否为同一条记录(对应)
		if (newData.getId().equals(oldData.getId())) {
			//主键对应上了,下面判断数据是否发生更改
			if (!newData.equals(oldData)) {
				//新旧数据不同,发生了更改,将更改落盘到数据库
				dataService.updateData(newData);
			} else {
				//新旧数据一致,说明没有发生更改,什么也不做
			}
			//新旧数据比对并操作后,将这两个数据从List中“移除”
			newData = null;
			oldData = null;
		}
		//两个数据主键没有对应上,说明不为同一条记录,继续遍历
	}
	//遍历完成之后,如果新数据在旧数据中有主键对应,则肯定会被置null
	//没被置null说明这条新数据是新增的,需要调用接口落盘
	if (newData != null) {
		dataService.insertData(newData);
	}
}

//遍历完新数据后,oldDataList中剩下的没被置null的都是需要删除的
for (Data oldData : oldDataList) {
	if (oldData != null) {
		dataService.deleteDataById(oldData.getId());
	}
}

//此时新旧数据库的内容就同步成一样的了
4、关于同步的建议

还是需要根据项目的需求来进行数据同步,比如有些场景对同步的速度没啥要求,再比如有些场景的数据量非常庞大,如果拿到内存中会oom。对于时间不敏感的同步,比如每天凌晨同步一次,则怎么稳定怎么来,逻辑怎么简单怎么来,哪怕要不停遍历,不要以为自己的逻辑想得太巧妙了,实际经常暗藏bug。

  • 5
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
可以通过以下步骤同步两个数据库中的数据不同表: 1. 连接两个数据库:使用 JDBC(Java 数据库连接)连接两个数据库。 2. 获取源数据库表中的数据:使用 SQL 语句查询源数据库中的数据,将结果集存储到 Java 对象中。 3. 转换数据格式:将 Java 对象中的数据格式转换成目标数据库表的格式。 4. 插入或更新数据:使用 SQL 语句将转换后的数据插入或更新到目标数据库表中。 5. 关闭连接:关闭 JDBC 连接以释放资源。 需要注意的是,如果数据量较大,可能会导致性能问题。因此,可以考虑使用批量插入或批量更新操作优化性能。 具体实现细节可以参考以下代码示例: ``` //连接源数据库 Connection sourceConn = DriverManager.getConnection(sourceUrl, sourceUsername, sourcePassword); //连接目标数据库 Connection targetConn = DriverManager.getConnection(targetUrl, targetUsername, targetPassword); //查询源数据库中的表数据 Statement stmt = sourceConn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM source_table"); //遍历结果集,转换数据格式并插入或更新到目标数据库中 PreparedStatement pstmt = targetConn.prepareStatement("INSERT INTO target_table (column1, column2, ...) VALUES (?, ?, ...)"); while (rs.next()) { // 转换数据格式 Object column1 = rs.getObject("column1"); Object column2 = rs.getObject("column2"); ... // 插入或更新数据 pstmt.setObject(1, column1); pstmt.setObject(2, column2); ... pstmt.executeUpdate(); } //关闭连接 rs.close(); stmt.close(); pstmt.close(); sourceConn.close(); targetConn.close(); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值