MySQL适配达梦数据库
MySQL适配达梦数据库
- 背景
- 1、环境与工具
- 2、引入依赖及配置
- 3、数据库脚本适配
- 4、sql语句适配
- 5、可能会遇到的异常
背景
因为国际局势的变化,国产化替代是如今重要的指导性思想,根据市场环境及公司的要求,需要对产品做达梦数据库的兼容。
1、环境与工具
首先需要部署一个达梦数据库的环境,可以到达梦官网去下载一个安装,我这边有专门的部门同事已经安装好测试环境,不必自己去安装。
使用达梦数据库时,可以用达梦自带的DM数据库管理工具,如果需要使用另外的数据库管理工具,可以下载安装SQLark白灵连接,目前可以免费使用。
2、引入依赖及配置
1、添加达梦数据库驱动依赖
com.dameng DmJdbcDriver18 8.1.1.193
2、修改配置文件
修改驱动依赖包为:spring.datasource.driver-class-name=dm.jdbc.driver.DmDriver
修改数据库连接url为:jdbc:dm://192.168.122.34:5236?schema=abc
如果不指定schema(即指定使用哪个数据库,在达梦指的是哪个schema),程序启动则会发生找不到对应的表的异常
3、添加方言包
如果程序使用了Hibernate JPA等对象映射框架,还需要引入方言,这里我们可以新建一个类,并进行配置
package com.car.config; import org.hibernate.dialect.Dialect; import org.hibernate.dialect.function.VarArgsSQLFunction; import org.hibernate.type.StringType; import java.sql.Types; /** * @Author cwl * @Date 2025-02-08 16:27 */ public class DmDialect extends Dialect { public DmDialect() { super(); registerColumnType(Types.BIT, "boolean"); registerColumnType(Types.BIGINT, "bigint"); registerColumnType(Types.SMALLINT, "smallint"); registerColumnType(Types.TINYINT, "tinyint"); registerColumnType(Types.INTEGER, "integer"); registerColumnType(Types.CHAR, "char(1)"); registerColumnType(Types.VARCHAR, "varchar($l)"); registerColumnType(Types.FLOAT, "float"); registerColumnType(Types.DOUBLE, "double"); registerColumnType(Types.DATE, "date"); registerColumnType(Types.TIME, "time"); registerColumnType(Types.TIMESTAMP, "timestamp"); registerColumnType(Types.BINARY, "binary"); registerColumnType(Types.VARBINARY, "varbinary($l)"); registerColumnType(Types.BLOB, "blob"); registerColumnType(Types.CLOB, "clob"); registerColumnType(Types.BOOLEAN, "boolean"); registerFunction("concat", new VarArgsSQLFunction(StringType.INSTANCE, "", "||", "")); } }
spring.datasource.driver-class-name=dm.jdbc.driver.DmDriver spring.datasource.url=jdbc:dm://192.168.122.34:5236?schema=abc spring.datasource.username=SYSDBA spring.datasource.password=root #达梦方言包 spring.jpa.database-platform=com.lancoo.car.config.DmDialect
3、数据库脚本适配
原MySQL数据库中创建数据库的脚本,可以做一些修改以适配达梦数据库。
1、创建数据库语句调整
MySQL创建数据库语句
CREATE DATABASE `name` ; USE `campuscar`;
替换为以模式(schema)形式的创建数据库
CREATE SCHEMA "name" ; ALTER SESSION SET CURRENT_SCHEMA = "name";/*设置当前会话*/
2、去掉utf-8等字符的设置
3、表名的单引号改为双引号,如`tableName`改为"tableName"
4、去掉 ON UPDATE CURRENT_TIMESTAMP, 改为触发器实现
5、索引单独实现
6、tinyint\int\bigint 后面不带数字
7、设置自增主键
# 从 1 开始,每次增加 1 "id" int IDENTITY(1, 1) NOT NULL COMMENT '主键id',
4、sql语句适配
1、 ifnull 名称改为 COALESCE
例如;ifnull(s.roomId,ao.roomId) as roomId 改为 COALESCE(s.roomId,ao.roomId) as roomId
2、 group_concat 方法需要修改
例如:group_concat(assetName) as applyAssetName 改为 LISTAGG(assetName, ', ') WITHIN GROUP (ORDER BY assetName) AS applyAssetName
5、可能会遇到的异常
1、达梦报错,发生变量空间溢出异常
原因是一次性插入了8838条记录,超过了在达梦数据库配置的缓存或者内存上限,可以对达梦数据库重新配置优化
也可以在程序中将超过1000个元素的列表拆开为小批量插入,设置1000为最大长度,拆开进行数据插入
这里可以新建一个工具类,使用Stream Api进行实现对数组的分割
package com.car.util; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; /** * @Author cwl * @Date 2025-02-10 16:08 */ public class CommonUtil { /** * 兼容达梦,列表数据插入之前先按默认最大1000分割列表 * @param largeList * @param * @return */ public static List DmInsertListSplit(List largeList){ return split(largeList, 1000); } /** * * @param largeList 原数组 * @param chunkSize 目标数组长度 * @return */ public static List split(List largeList, int chunkSize){ List smallLists = IntStream.range(0, largeList.size() / chunkSize + 1) .mapToObj(i -> largeList.subList(i * chunkSize, Math.min((i + 1) * chunkSize, largeList.size()))) .collect(Collectors.toList()); return smallLists; } }
大量数据的列表分割成小列表后,成功将数据插入达梦数据库
2、设置了自增主键后,不能手动给主键赋值,如果需要手动赋值,需要先用命令打开限制
用命令打开限制
# 若需手动赋值,需要先在当前环境打开 SET IDENTITY_INSERT MyTable ON; -- 允许对自增列赋值 # 数据插入后,建议关闭 SET IDENTITY_INSERT MyTable OFF; -- 关闭对自增列的显式赋值
3、给字段赋值空字符串时需要用单引号
4、sql脚本内有注释会导致 Cause: dm.jdbc.driver.DMException: 序列号无效,需要将注释删除
5、使用SQLark工具进行sql操作时,注意更新的sql操作需要加上事务提交 commit,否则更新不会提交,并且该事务一直未提交,会影响到其他事务的正常进行,达梦会报一些 jdbcType=null, 序列号无效之类的错误
update parent set parName = 'chen' where stuUserId = 'S01001'; # 如果没有隐式的事务自动提交,则此处需要显式地进行事务提交 commit ;