国产数据库适配:五个心得分享

1,136 阅读2分钟

前言

随着国产化浪潮的兴起,我们的项目组面临了一项新的挑战:将现有的Oracle数据库迁移并适配到国产数据库平台,如达梦、人大金仓、MySQL和PostgreSQL。这一过程中,我们遇到了数据类型、语法和函数等关键差异,这无疑增加了迁移的复杂性。经过数日的深入研究和团队成员间的紧密协作,我们不仅成功地完成了这一任务,还积累了宝贵的经验。在本文中,我将分享我们在这一过程中的心得体会,希望能为同样面临数据库国产化挑战的同行提供参考和启发。

正文

  1. 在设计数据库时,推荐统一使用字符型(如 VARCHAR)字段,以简化跨数据源同步并减少数据类型不一致带来的适配问题

  2. 建议使用工具(如Dbeaver、Navicat)来同步数据库结构

  3. 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();
             }
         }
        
  4. 如有部分函数不存在的情况,可以创建同名函数,以下是Postgresql中创建NVL的例子

    •  CREATE OR REPLACE FUNCTION NVL(input ANYELEMENT, replacement ANYELEMENT)
       RETURNS ANYELEMENT AS $$
       BEGIN
           RETURN COALESCE(input, replacement);
       END;
       $$ LANGUAGE plpgsql;
      
    • 推荐使用AI工具实现函数的转换(Kimi、通义千问、智谱清言等)
  5. 同一方法如果需要根据不同数据源采取不同的实现,建议使用策略模式,以下为示例代码

    •  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语句执行。我们项目中采取的策略是在业务层进行这样的拆分,以确保兼容性。