一、一个被广泛误解的观点 在不少技术社区里,有一种说法流传很广:
“只要项目用了ORM,换数据库就是改个方言配置的事,根本不需要什么迁移工具。”
这个观点听起来很有道理。ORM确实屏蔽了大部分SQL差异,Hibernate、MyBatis、Entity Framework这些框架都提供了数据库方言抽象。如果项目从MySQL换到PostgreSQL,理论上只需要修改连接配置和方言,应用层代码几乎不用动。
但现实真的这么简单吗?
去年我接手了一个信创项目,把一套跑了6年的Oracle系统迁移到达梦DM8。项目用了MyBatis,按理说ORM层已经处理了大部分SQL差异。但实际迁移过程让我发现——ORM解决的是“应用层怎么写SQL”,而数据库迁移解决的是“底层数据怎么搬”。这是两件完全不同的事。
二、真实项目背景 源库:Oracle 11g,200多张表,3000多万行数据
目标库:达梦DM8
应用层:Java + MyBatis
数据库对象:100多个存储过程、30多个视图、若干触发器和序列
项目组一开始的判断是:ORM都用了,迁移应该不难。结果证明,这个判断错得离谱。
三、ORM管不了的四个层面 第一层:数据库对象迁移
MyBatis能处理应用层的SQL映射,但存储过程、视图、触发器、序列、自定义函数——这些数据库对象ORM一概不管。
我们那100多个存储过程,全是业务逻辑的核心。每个存储过程里都有Oracle特有的语法:NVL、DECODE、ROWNUM、%TYPE、PRAGMA AUTONOMOUS_TRANSACTION。MyBatis的方言配置对这些完全无能为力。
最终这些存储过程是用DBBridge做语法转换的。DBBridge自动识别了大部分语法差异并生成达梦兼容的PL/SQL,对于无法自动转换的部分在报告中标记出来,我们再人工复核。100多个存储过程,工具处理了70%左右,剩下30%复杂逻辑花了3天人工校验。
第二层:数据类型映射
MyBatis的jdbcType只能处理Java类型和JDBC类型的对应关系。但Oracle的NUMBER(10,2)到达梦应该映射成什么?VARCHAR2(255 CHAR)到达梦的长度语义是什么?DATE类型在Oracle里包含时分秒,到达梦是不是还一样?
这些类型映射的细节,ORM完全不管。而迁移工具必须管——因为类型映射错了,数据就可能出错。
第三层:数据一致性
ORM负责的是“读写数据”,不负责“校验数据”。迁移完成后,源库和目标库的行数是否一致?关键字段的值是否一致?金额计算有没有精度损失?
这些校验必须由迁移工具或人工脚本完成。DBBridge的迁移报告会列出每张表的迁移行数,我们再用脚本对比源库和目标库的关键字段校验和,才敢确认数据完整。
第四层:迁移过程的安全保障
迁移过程中如果失败,ORM不会帮你回滚。迁移前如果目标库有同名表,ORM不会帮你备份。
这些安全保障是迁移工具的核心能力。DBBridge在迁移前自动把目标库同名表重命名为 bak前缀,迁移失败可以一键回滚。这个功能在我们迁移过程中救过一次——有一张表因为字符集问题迁移中断,目标库只写入了一半数据,直接一键回滚恢复。
四、ORM的真正价值 说了这么多,并不是否定ORM。ORM的价值在于:
提高应用层开发效率
减少手写SQL的工作量
提供一定程度的数据库无关性
但它的能力边界也很清晰:它解决的是应用层的数据库访问问题,不是数据库迁移问题。
如果你的系统只有简单的CRUD,没有存储过程、没有复杂类型、没有数据库特有语法——那ORM确实能让迁移变轻松。
但现实中,需要迁移的系统往往已经跑了多年,积累了大量数据库对象和特有语法。这种情况下,ORM帮不了你,你需要的是专业的迁移工具。
五、结论 ORM和迁移工具不是替代关系,是互补关系。
应用层:用ORM,屏蔽SQL差异
数据库层:用迁移工具,处理类型映射、对象迁移、数据搬运
项目地址:
GitHub:suoten/dbbridge
Gitee:suoten/dbbridge
欢迎 Star、Issue、PR。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70050062/viewspace-3184167/ ,如需转载,请注明出处,否则将追究法律责任。