前言
随着国产化浪潮的兴起,我们的项目组面临了一项新的挑战:将现有的Oracle数据库迁移并适配到国产数据库平台,如达梦、人大金仓、MySQL和PostgreSQL。这一过程中,我们遇到了数据类型、语法和函数等关键差异,这无疑增加了迁移的复杂性。经过数日的深入研究和团队成员间的紧密协作,我们不仅成功地完成了这一任务,还积累了宝贵的经验。在本文中,我将分享我们在这一过程中的心得体会,希望能为同样面临数据库国产化挑战的同行提供参考和启发。
正文
-
在设计数据库时,推荐统一使用字符型(如 VARCHAR)字段,以简化跨数据源同步并减少数据类型不一致带来的适配问题
-
建议使用工具(如Dbeaver、Navicat)来同步数据库结构
-
mybatis中使用以下标签来适配不同数据源的sql
-
<if test="_databaseId == 'Oracle'"></if>
-
|| _databaseId == 'Oracle' || _databaseId == 'DM DBMS' || _databaseId == 'KingbaseES' || _databaseId == 'PostgreSQL' || _databaseId == 'MySQL'
-
mybatis中还需要实现DatabaseIdProvider接口以获取_databaseId
-
@Component public class MybatisDatabaseIdProvider implements DatabaseIdProvider { private String dbName; public String getDbName() { return dbName; } public void setDbName(String dbName) { this.dbName = dbName; } @Override public void setProperties(Properties p) { } @Override public String getDatabaseId(DataSource dataSource) throws SQLException { Connection conn = dataSource.getConnection(); String dbName = conn.getMetaData().getDatabaseProductName(); this.setDbName(dbName); return dbName; } @Bean("dbName") public String dbName(){ return this.getDbName(); } }
-
-
-
如有部分函数不存在的情况,可以创建同名函数,以下是Postgresql中创建NVL的例子
-
CREATE OR REPLACE FUNCTION NVL(input ANYELEMENT, replacement ANYELEMENT) RETURNS ANYELEMENT AS $$ BEGIN RETURN COALESCE(input, replacement); END; $$ LANGUAGE plpgsql;
- 推荐使用AI工具实现函数的转换(Kimi、通义千问、智谱清言等)
-
-
同一方法如果需要根据不同数据源采取不同的实现,建议使用策略模式,以下为示例代码
-
public interface ModelStrategy { String doStrategy(Param param); }
-
public class OracleModelStrategy implements ModelStrategy { @Override public String doStrategy(Param param) { String res = ""; // do something return res; } }
-
public class PostgreSqlModelStrategy implements ModelStrategy { @Override public String doStrategy(Param param) { String res = ""; // do something return res; } }
-
public class ModelTool { private static Map<String, ModelStrategy> modelStrategyMap = new HashMap<>(); static { reportModelStrategyMap.put("Oracle", new OracleReportModelStrategy()); reportModelStrategyMap.put("PostgreSQL", new PostgreSQLReportModelStrategy()); } public static ModelStrategy getModelStrategy(String dbName){ return modelStrategyMap.get(dbName); } }
-
public class Test { @Resource(name = "dbName") private String dbName; public static void main(String[] args) { ModelStrategy strategy = ModelTool.getModelStrategy(dbName) Param param = new Param(); strategy.doStrategy(param); } }
-
结尾
国产化数据库迁移虽然复杂,但并非不可克服。面对数据库语法转换难题,利用AI工具可以显著提高效率。例如,Oracle特有的
MERGE INTO
语句在MySQL和PostgreSQL中不存在,需要深入理解其逻辑并拆分为多个简单SQL语句执行。我们项目中采取的策略是在业务层进行这样的拆分,以确保兼容性。