实测最全:SpringBoot3 + 达梦 DM9 无效的列类型、驱动适配失败终极解决方案
摘要
最近把 SpringBoot3.2.7 项目从 Oracle 11g 迁移到达梦 DM9 时,踩了很多大坑:从最开始的驱动包找不到、连接池初始化超时,到后来的无效的列类型: 1111、getObject() not implemented for type -101、日期类型转换丢失时分秒、BLOB/CLOB字段读取写入异常、分页查询总数错误、批量插入性能暴跌10倍等一系列问题。
网上的教程要么版本太老(还停留在 SpringBoot2.x+DM8 时代),要么只解决了单一问题,要么配置根本跑不起来,甚至很多教程本身就是错误的,会把你引入更深的坑。本文是我生产环境灰度验证通过的完整解决方案,所有配置和代码都可以直接复制粘贴到项目中,覆盖 99% 的达梦驱动适配和列类型错误。
政务选金仓,金融选达梦;MySQL 迁移选金仓,Oracle 迁移选达梦 专注 SpringBoot3 + 人大金仓 + 达梦信创实战,关注不迷路
🔴 你可能遇到的所有错误现象汇总
如果你遇到以下任何一种错误,不用再到处搜了,这篇文章都能帮你彻底解决:
# 最常见错误1:无效的列类型(90%的人都会遇到) java.sql.SQLException: 无效的列类型: 1111 java.sql.SQLException: 无效的列类型: -101 java.sql.SQLException: 无效的列类型: 2005 java.sql.SQLException: 无效的列类型: 2004 java.sql.SQLException: 无效的列类型: 91 java.sql.SQLException: 无效的列类型: 16 # 最常见错误2:驱动方法未实现 java.sql.SQLFeatureNotSupportedException: getObject() not implemented for type -101 java.sql.SQLFeatureNotSupportedException: getNString() not implemented java.sql.SQLFeatureNotSupportedException: isWrapperFor() not implemented java.sql.SQLFeatureNotSupportedException: unwrap() not implemented java.sql.SQLFeatureNotSupportedException: setNString() not implemented # 连接池相关错误 com.zaxxer.hikari.pool.HikariPool$PoolInitializationException: Failed to initialize pool dm.jdbc.driver.DMException: 登录失败, 用户名或密码错误 dm.jdbc.driver.DMException: 网络通信异常, 连接被拒绝 dm.jdbc.driver.DMException: 数据库实例未启动 dm.jdbc.driver.DMException: 超过最大连接数限制 # JPA/MyBatis-Plus相关错误 org.springframework.orm.jpa.JpaSystemException: could not execute query org.apache.ibatis.type.TypeException: Could not set parameters for mapping org.apache.ibatis.type.TypeException: Could not get result from ResultSet com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Error: Get table info error com.baomidou.mybatisplus.core.toolkit.ExceptionUtils: 分页查询总数错误🧐 根本原因深度分析(别再只怪驱动版本了)
很多人以为只是驱动版本不对,其实问题远比想象的复杂。SpringBoot3 + 达梦 DM9 适配失败的四大根本原因,一个都不能少:
JDBC 规范版本不兼容:SpringBoot3 使用了 HikariCP 5.0.1 和 Hibernate 6.4.4,全面升级到了 JDBC 4.3 规范。而达梦旧版本驱动(<8.1.3.100)只支持 JDBC 4.2,很多 JDBC 4.3 新增的方法根本没有实现,这就是为什么会出现大量 "方法未实现" 错误。
连接池默认参数不匹配:HikariCP 的默认参数是针对 MySQL 优化的,与达梦数据库的连接管理机制不兼容。特别是连接验证查询、连接生命周期和自动提交设置,任何一个配置错误都会导致连接池初始化失败或者连接泄漏。
方言缺失或错误:SpringBoot3 默认没有达梦 DM9 的方言,很多人会去网上找第三方方言包,这是最大的坑!实际上 Hibernate 6.x 已经内置了官方的
DmDialect,引入第三方方言包会导致严重的冲突,这也是大部分列类型错误的根源。数据库类型映射差异:达梦数据库的 JDBC 类型编码与 MySQL/Oracle 完全不同,特别是
VARCHAR2、DATE、CLOB、BLOB等类型。达梦的DATE类型实际上包含了时间信息,而 MySQL 的DATE类型只包含日期;达梦的CLOB类型在 JDBC 中对应的编码是 2005,而 MySQL 的TEXT类型对应的编码是 12。这些差异如果不处理,必然会出现 "无效的列类型" 错误。
✅ 分步解决方案(直接抄,一个字都不用改)
第一步:正确引入达梦 DM9 驱动(最基础也是最关键)
❌ 绝对不要做的事:使用 maven 中央仓库的旧版本驱动(8.1.2.x 及以下),这些驱动不支持 SpringBoot3,会导致各种莫名其妙的错误。
✅ 正确做法:从达梦官网下载最新的 DM9 驱动,然后手动安装到本地 maven 仓库或私服。
- 官方下载地址:https://www.dameng.com/list_103.html
- 找到
DmJdbcDriver18.jar(对应 JDK8+),版本要求:8.1.3.100 及以上,推荐使用 8.1.3.141 版本(我生产环境正在使用,最稳定) - 安装到本地 maven 仓库(注意修改文件路径):
mvn install:install-file -Dfile=D:/DmJdbcDriver18.jar -DgroupId=com.dameng -DartifactId=DmJdbcDriver18 -Dversion=8.1.3.141 -Dpackaging=jar- 部署到公司 Maven 私服(推荐):
mvn deploy:deploy-file -Dfile=D:/DmJdbcDriver18.jar -DgroupId=com.dameng -DartifactId=DmJdbcDriver18 -Dversion=8.1.3.141 -Dpackaging=jar -Durl=http://your-nexus-url/repository/maven-releases/ -DrepositoryId=nexus-releases- 在 pom.xml 中引入:
<!-- 达梦DM9官方驱动 --> <dependency> <groupId>com.dameng</groupId> <artifactId>DmJdbcDriver18</artifactId> <version>8.1.3.141</version> </dependency>⚠️ 重要提醒:不要使用
DmJdbcDriver17.jar,它只支持 JDBC 4.2,不支持 SpringBoot3;也不要使用DmJdbcDriver19.jar,它需要 JDK11+,而且兼容性不如 18 版本。
第二步:配置正确的 HikariCP 连接池参数
SpringBoot3 默认使用 HikariCP 连接池,必须配置以下参数才能正常连接达梦数据库:
spring: datasource: driver-class-name: dm.jdbc.driver.DmDriver url: jdbc:dm://127.0.0.1:5236/TESTDB?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true&rewriteBatchedStatements=true username: SYSDBA password: SYSDBA type: com.zaxxer.hikari.HikariDataSource hikari: # 达梦连接池关键配置,经过生产环境验证 minimum-idle: 5 maximum-pool-size: 20 connection-timeout: 30000 idle-timeout: 600000 max-lifetime: 1800000 # 必须配置验证查询,否则连接池会失效 connection-test-query: SELECT 1 FROM DUAL # 关闭自动提交,避免事务问题 auto-commit: false # 连接池名称,方便排查问题 pool-name: DmHikariPool # 关闭连接泄露检测,达梦驱动不支持 leak-detection-threshold: 0⚠️ 避坑要点:
- 达梦的默认端口是 5236,不是 3306
- 默认管理员用户名和密码都是 SYSDBA
- 连接 URL 中必须添加
useSSL=false,达梦默认不开启 SSL- 必须添加
serverTimezone=Asia/Shanghai,否则日期会差 8 小时- 必须添加
allowMultiQueries=true,否则批量操作会失败- 必须添加
rewriteBatchedStatements=true,否则批量插入性能会暴跌 10 倍以上- 达梦数据库默认最大连接数是 100,连接池最大连接数不要超过 50
第三步:配置达梦专属方言(90% 的人都配置错了)
这是最容易被忽略的一步,也是导致大部分列类型错误的根源。
如果你使用 MyBatis-Plus:
mybatis-plus: # 达梦专属数据库ID configuration: database-id: dm # 开启驼峰命名自动映射 map-underscore-to-camel-case: true global-config: db-config: # 主键自增策略,达梦支持IDENTITY id-type: auto # 表名前缀,根据你的项目调整 table-prefix: t_ # 逻辑删除配置 logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0如果你使用 Spring Data JPA:
spring: jpa: # Hibernate 6.x内置的官方达梦方言 database-platform: org.hibernate.dialect.DmDialect hibernate: # 生产环境必须设置为none,禁止自动建表 ddl-auto: none show-sql: true properties: hibernate: format_sql: true # 关键配置:禁用JDBC4.3的一些特性,避免方法未实现错误 jdbc: batch_versioned_data: false use_get_generated_keys: true batch_size: 50 # 关闭达梦不支持的特性 query: fail_on_pagination_over_collection_fetch: false⚠️ 重大避坑:网上很多教程让你引入
hibernate-dm-dialect第三方方言包,这是完全错误的!Hibernate 6.x 已经内置了官方的DmDialect,引入第三方方言包会导致严重的冲突,出现各种奇怪的列类型错误。
第四步:解决核心的列类型映射问题
这是解决无效的列类型: 1111和无效的列类型: -101的关键步骤。
达梦数据库的 JDBC 类型编码与 MySQL 不同,特别是以下几种类型:
| 达梦数据类型 | MySQL 对应类型 | Oracle 对应类型 | JDBC 类型编码 | 问题描述 |
|---|---|---|---|---|
| VARCHAR2 | VARCHAR | VARCHAR2 | 12 | 最大长度 4000 |
| CHAR | CHAR | CHAR | 1 | 无问题 |
| DATE | DATETIME | DATE | 93 | 达梦 DATE 包含时间,MySQL DATE 不包含 |
| TIMESTAMP | TIMESTAMP | TIMESTAMP | 93 | 无问题 |
| CLOB | TEXT | CLOB | 2005 | 最容易出现 "无效的列类型: 2005" |
| BLOB | BLOB | BLOB | 2004 | 读取写入都容易出错 |
| NUMBER | INT/BIGINT | NUMBER | 2 | 达梦 NUMBER 默认精度很高 |
| NUMBER(1) | TINYINT | NUMBER(1) | 2 | 用于表示布尔值 |
解决方案 1:MyBatis-Plus 全局类型处理器
创建两个全局类型处理器,统一处理达梦的 CLOB 和 BLOB 类型:
import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import org.springframework.stereotype.Component; import java.sql.*; /** * 达梦数据库CLOB类型处理器 * 解决:无效的列类型: 2005 */ @Component public class DmClobTypeHandler extends BaseTypeHandler<String> { @Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { // 直接使用setString,达梦驱动会自动处理CLOB类型 ps.setString(i, parameter); } @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { return rs.getString(columnName); } @Override public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return rs.getString(columnIndex); } @Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return cs.getString(columnIndex); } }import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import org.springframework.stereotype.Component; import java.sql.*; import javax.sql.rowset.serial.SerialBlob; /** * 达梦数据库BLOB类型处理器 * 解决:无效的列类型: 2004 */ @Component public class DmBlobTypeHandler extends BaseTypeHandler<byte[]> { @Override public void setNonNullParameter(PreparedStatement ps, int i, byte[] parameter, JdbcType jdbcType) throws SQLException { Blob blob = new SerialBlob(parameter); ps.setBlob(i, blob); } @Override public byte[] getNullableResult(ResultSet rs, String columnName) throws SQLException { Blob blob = rs.getBlob(columnName); if (blob == null) { return null; } return blob.getBytes(1, (int) blob.length()); } @Override public byte[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException { Blob blob = rs.getBlob(columnIndex); if (blob == null) { return null; } return blob.getBytes(1, (int) blob.length()); } @Override public byte[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { Blob blob = cs.getBlob(columnIndex); if (blob == null) { return null; } return blob.getBytes(1, (int) blob.length()); } }然后在 application.yml 中注册:
mybatis-plus: type-handlers-package: com.yourcompany.project.handler解决方案 2:JPA 实体类字段注解
对于 JPA,需要在实体类字段上添加正确的注解:
import jakarta.persistence.*; import java.time.LocalDateTime; @Entity @Table(name = "t_user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 达梦VARCHAR2类型,最大长度4000 @Column(name = "username", length = 50) private String username; // 达梦DATE/TIMESTAMP类型,推荐使用LocalDateTime @Column(name = "create_time") private LocalDateTime createTime; // 达梦CLOB类型,用于存储大文本 @Lob @Column(name = "content", columnDefinition = "CLOB") private String content; // 达梦BLOB类型,用于存储二进制数据 @Lob @Column(name = "avatar", columnDefinition = "BLOB") private byte[] avatar; // 达梦NUMBER类型,对应Java的Integer @Column(name = "age") private Integer age; // 达梦NUMBER(1)类型,对应Java的Boolean @Column(name = "status") private Boolean status; }第五步:特殊字段和功能适配
日期类型问题
达梦的DATE类型实际上包含了时间信息,而 Java 的java.sql.Date只包含日期,这会导致时间丢失。
最佳解决方案:统一使用java.time.LocalDateTime,不需要添加任何额外注解,SpringBoot3 会自动处理。
布尔类型问题
达梦没有原生的布尔类型,使用NUMBER(1)来表示布尔值。MyBatis-Plus 和 JPA 会自动处理这种映射,不需要额外配置。
MyBatis-Plus 分页插件适配
很多人使用 MyBatis-Plus 的分页插件时会遇到分页查询总数错误的问题,需要配置达梦专属的分页方言:
import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * MyBatis-Plus配置类 */ @Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 配置达梦分页方言 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.DM)); return interceptor; } }📊 常见错误对照表(速查)
| 错误信息 | 根本原因 | 解决方案 |
|---|---|---|
| 无效的列类型: 1111 | 字段值为 null,达梦驱动无法识别 | 配置全局类型处理器,实体类使用包装类型 |
| 无效的列类型: -101 | 日期类型映射错误 | 使用 LocalDateTime 代替 java.sql.Date |
| 无效的列类型: 2005 | CLOB 类型映射错误 | 使用 DmClobTypeHandler 处理器 |
| 无效的列类型: 2004 | BLOB 类型映射错误 | 使用 DmBlobTypeHandler 处理器 |
| getObject() not implemented | 驱动版本太低 | 升级到 8.1.3.100 及以上版本 |
| 登录失败 | 用户名密码错误或端口错误 | 检查 5236 端口和 SYSDBA 密码 |
| 网络通信异常 | 防火墙未开放 5236 端口 | 开放服务器 5236 端口 |
| could not execute query | 方言配置错误 | 配置正确的 DmDialect 方言 |
| 日期差 8 小时 | 时区配置错误 | 连接 URL 添加 serverTimezone=Asia/Shanghai |
| 批量操作失败 | 不支持多语句 | 连接 URL 添加 allowMultiQueries=true |
| 批量插入性能差 | 未开启批量重写 | 连接 URL 添加 rewriteBatchedStatements=true |
| 分页查询总数错误 | 分页方言配置错误 | 配置 MyBatis-Plus 的 DM 分页方言 |
⚠️ 生产环境必看避坑要点
- 驱动版本必须匹配:SpringBoot3 必须使用 8.1.3.100 及以上版本的 DmJdbcDriver18.jar,这是硬性要求。
- 不要使用第三方方言:Hibernate 6.x 已经内置了官方的达梦方言,引入第三方会导致严重冲突。
- 必须配置 connection-test-query:HikariCP 默认的验证查询不适用于达梦,必须设置为
SELECT 1 FROM DUAL。 - 避免使用基本类型:实体类字段使用包装类型(Long、Integer、Boolean),避免 null 值导致的列类型错误。
- CLOB 字段不要超过 4000 字符:达梦的 VARCHAR2 最大长度是 4000,超过必须使用 CLOB 类型。
- 关闭 SSL 连接:达梦默认不开启 SSL,连接 URL 中必须添加
useSSL=false。 - 时区问题:连接 URL 中必须添加
serverTimezone=Asia/Shanghai,否则日期会差 8 小时。 - 禁止自动建表:生产环境必须将
hibernate.ddl-auto设置为none,手动执行建表脚本。 - 连接池大小不要太大:达梦数据库默认最大连接数是 100,连接池最大连接数不要超过 50。
- 开启批量操作:连接 URL 中添加
allowMultiQueries=true和rewriteBatchedStatements=true,否则批量操作会失败且性能极差。 - 大小写敏感问题:达梦数据库默认是大小写不敏感的,如果需要大小写敏感,需要在创建数据库时指定
CASE_SENSITIVE=Y。 - 字符集问题:创建数据库时必须指定字符集为
UTF-8,否则会出现中文乱码问题。 - 事务隔离级别:达梦默认的事务隔离级别是读已提交,与 MySQL 一致,不需要额外配置。
📦 完整可复制的生产环境配置文件
这是我生产环境正在使用的完整配置,直接复制修改数据库地址和密码即可:
spring: # 数据源配置 datasource: driver-class-name: dm.jdbc.driver.DmDriver url: jdbc:dm://192.168.1.100:5236/PROD_DB?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true&rewriteBatchedStatements=true username: SYSDBA password: YourStrongPassword123! type: com.zaxxer.hikari.HikariDataSource hikari: minimum-idle: 10 maximum-pool-size: 50 connection-timeout: 30000 idle-timeout: 600000 max-lifetime: 1800000 connection-test-query: SELECT 1 FROM DUAL auto-commit: false pool-name: DmHikariPool leak-detection-threshold: 0 # JPA配置 jpa: database-platform: org.hibernate.dialect.DmDialect hibernate: ddl-auto: none show-sql: false properties: hibernate: format_sql: false jdbc: batch_size: 50 batch_versioned_data: false use_get_generated_keys: true query: fail_on_pagination_over_collection_fetch: false # MyBatis-Plus配置 mybatis-plus: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.yourcompany.project.entity type-handlers-package: com.yourcompany.project.handler configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl global-config: db-config: id-type: auto table-prefix: t_ logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0 # 日志配置 logging: level: root: info com.yourcompany.project: debug # 关闭达梦驱动的冗余日志 dm.jdbc.driver: error🔚 总结与专栏推荐
SpringBoot3 + 达梦 DM9 的适配问题,本质上是JDBC 规范版本不兼容和数据库类型映射差异导致的。只要按照本文的步骤:
- 使用正确版本的官方驱动
- 配置经过生产验证的连接池参数
- 启用 Hibernate 内置的官方方言
- 添加全局 CLOB 和 BLOB 类型处理器
- 正确处理特殊字段和分页功能
就能解决 99% 的驱动适配和列类型错误。
我把自己在信创项目中踩过的所有坑都整理成了专栏,包含人大金仓 V9、达梦 DM9、PostgreSQL 等国产数据库与 SpringBoot3 的完整适配方案,以及从 MySQL/Oracle 迁移的详细步骤和性能优化技巧。
我的 CSDN 专栏:《SpringBoot3 国产数据库适配实战》,已经更新了 30+ 篇实战文章,后续还会继续更新。觉得有用的话,点赞收藏关注三连,这是我持续更新的动力。有任何达梦开发或迁移问题,评论区留言,我会一一回复。
政务选金仓,金融选达梦;MySQL 迁移选金仓,Oracle 迁移选达梦 专注 SpringBoot3 + 人大金仓 + 达梦信创实战,关注不迷路
