一、依赖配置
开发环境集成可参考达梦官网:开发环境准备。
这里以达梦 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 语法改写以及回归测试。
1、关键字冲突可用双引号
查询达梦数据库出现关键字冲突不能使用 ``,建议使用双引号区分。
对应到 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 对象。
4、BLOB 与 CLOB 类型字段不支持排序或比较
达梦对于 CLOB 等大字段类型不支持比较、排序、聚合等,比如定义了一个 clob 类型的字段 x,查询语句就不能对该字段使用 distinct、order by 等,select distinct m, n, x from t where m = 1 也会报错【试图在blob或者clob列上排序或比较】。
解决方法推荐使用 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 格式。
6、TEXT 或 CLOB 类型字段无法转换为 Java String 对象是驱动缺陷
这个是 JDBC 驱动 bug,读取 text 或者 clob 字段(包括使用函数返回的字段类型)得到的是一个 DmdbNClob 对象。可以在连接属性上添加clobAsString=true解决。
四、最佳实践小结
1、连接属性优化
添加连接属性返回字段不转换为大写,CLOB 字段类型转换为 String:
jdbc.url=jdbc:dm://localhost:5236?columnNameUpperCase=false&clobAsString=true
2、函数检查
所有使用函数的都要特别检查,确定达梦有对应函数支持。
3、字段类型显式转换
避免隐式转换带来的兼容性问题,比如精度丢失、类型不匹配等,尤其是时间类型、大字段类型。
4、大小写敏感查询
查询达梦是否大小写敏感,1 代表大小写敏感,0 代表大小写不敏感:
SELECT SF_GET_CASE_SENSITIVE_FLAG();
表名、字段名与字段值大小写敏感说明见:字符串大小写敏感使用说明。