MySQL 迁移达梦 SpringBoot 改造方法小结

806 阅读3分钟

一、依赖配置

开发环境集成可参考达梦官网:开发环境准备

这里以达梦 V8 版本为例,使用 SpringBoot 作为脚手架(SpringBoot3 依赖 mybatis-plus-spring-boot3-starter),以及 Mybatis-plus(版本至少 3.0) 作为 ORM 框架可添加如下配置。

jdbc.properties:

jdbc.driver=dm.jdbc.driver.DmDriver
jdbc.url=jdbc:dm://localhost:5236
jdbc.username=SYSDBA
jdbc.password=SYSDBA

pom.xml:

<dependency>
    <groupId>com.dameng</groupId>
    <artifactId>DmJdbcDriver18</artifactId>
    <version>8.1.1.193</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.10.1</version>
</dependency>

二、停机数据迁移

参考达梦官网提供的数据迁移方案MySQL 数据迁移方案):

  • 停止应用;
  • 确认要迁移的用户(模式、数据库);
  • 记录原数据库中要迁移的对象的数量;
  • 记录原数据库中要迁移的所有对象名称;
  • 记录原数据库中要迁移的表的数据量(行数);
  • 创建目标数据及实例;
  • 创建目标数据的表空间及用户。

三、SQL 适配

相对于存量数据迁移,语法适配需要更多关注,ORM 字段映射、SQL 语法改写以及回归测试。

image-20250124100904259.png

1、关键字冲突可用双引号

查询达梦数据库出现关键字冲突不能使用 ``,建议使用双引号区分。

image-20250121151056395.png 对应到 Mybatis,比如表结构定义了一个字段名为 function 可以添加注解处理:

@TableField("\"function\"")
private String function;

2、字符串比较与赋值不能使用双引号

字符串比较与赋值最好不要使用双引号,会出现报错【标示符长度非法】,可以使用单引号或函数处理。

比如字符串判空:

select * from xxx where xxx != ''

3、查询结果映射到 Java 对象全部转为了小写

执行 SQL 指定返回字段按照小驼峰等命名风格,但是全部返回大写字段,可添加扩展连接属性 columnNameUpperCase=false 解决。这样就可以按照指定的字段名返回结果,比如:

select xxx.user_name userName, xxx.createTime createTime xxx

达梦 8.1.1.193 JDBC 驱动默认将 columnNameUpperCase 置为 true(dm.jdbc.desc.Configuration),就会导致所有返回字符全部大写。Mybatis 无法按照下划线等方式解析就变成了全小写字符映射给了 Java 对象。

image-20250121174243439.png

4、BLOB 与 CLOB 类型字段不支持排序或比较

达梦对于 CLOB 等大字段类型不支持比较、排序、聚合等,比如定义了一个 clob 类型的字段 x,查询语句就不能对该字段使用 distinct、order by 等,select distinct m, n, x from t where m = 1 也会报错【试图在blob或者clob列上排序或比较】。

image-20250122151708578.png

解决方法推荐使用 lob 函数处理,dbms_lob.substr(x)。

但要注意仍然会对字符进行截断,BLOB 是 32767 字节,CLOB 是 32767 字符。

5、group_concat 函数替换

使用了 MySQL 字符串拼接函数 group_concat,就会报错【此处表达式不允许出现DISTINCT/ ALL或者*】,其实是函数不支持引起的,解决方法使用 wm_concat 或者 listagg 替换。

查询结果上来看,group_concat(xxx.xxx) 等同于 wm_concat(xxx.xxx) 也等同于 listagg(xxx.xxx, ',')。如果需要考虑超长字符聚合长度问题(超过 32767 字节)可使用 listagg2,它返回了 CLOB 格式。

image-20250122112047566.png

6、TEXT 或 CLOB 类型字段无法转换为 Java String 对象是驱动缺陷

这个是 JDBC 驱动 bug,读取 text 或者 clob 字段(包括使用函数返回的字段类型)得到的是一个 DmdbNClob 对象。可以在连接属性上添加clobAsString=true解决。

image-20250122151820588.png

四、最佳实践小结

1、连接属性优化

添加连接属性返回字段不转换为大写,CLOB 字段类型转换为 String:

jdbc.url=jdbc:dm://localhost:5236?columnNameUpperCase=false&clobAsString=true

2、函数检查

所有使用函数的都要特别检查,确定达梦有对应函数支持。

3、字段类型显式转换

避免隐式转换带来的兼容性问题,比如精度丢失、类型不匹配等,尤其是时间类型、大字段类型。

4、大小写敏感查询

查询达梦是否大小写敏感,1 代表大小写敏感,0 代表大小写不敏感:

SELECT SF_GET_CASE_SENSITIVE_FLAG();

表名、字段名与字段值大小写敏感说明见:字符串大小写敏感使用说明