这个问题涉及到 MyBatis 处理达梦数据库 (DM Database) 的 DmdbNClob 类型数据时的映射问题。让我搜索一下相关的技术资料和解决方案。

搜索网页

MyBatis DmdbNClob LinkedHashMap 查询结果为空 MyBatis 达梦数据库 CLOB 类型映射问题 MyBatis selectMap DM数据库 CLOB字段丢失 达梦数据库 MyBatis CLOB NCLOB 类型处理

53 个结果

根据搜索结果,我找到了您问题的根本原因和解决方案。这是达梦数据库 JDBC 驱动的已知特性/缺陷导致的。

问题原因

当使用 MyBatis 的 select 方法返回 LinkedHashMap 时,达梦数据库的 DmdbNClob 类型不会被自动转换为 Java String,而是以 DmdbNClob 对象形式存在。这会导致:

  1. 在 Map 中看不到该字段(可能被过滤或显示为对象引用)

  2. 序列化时报错(循环引用问题)

  3. 无法直接作为字符串使用

这是达梦数据库 JDBC 驱动的特性,不是 MyBatis 的问题。

解决方案(推荐顺序)

方案 1:JDBC URL 添加参数(最简单,推荐)

在数据库连接 URL 后添加 clobAsString=1clobAsString=true

properties

复制

# application.properties 或 application.yml
spring.datasource.url=jdbc:dm://localhost:5236/TEST?clobAsString=1

或完整配置:

properties

复制

jdbc:dm://localhost:5236?schema=your_schema&clobAsString=true&compatibleMode=mysql

原理:强制驱动将所有 CLOB/NCLOB 类型作为 String 返回。


方案 2:SQL 层面转换(无需改配置)

在 SQL 查询中使用函数将 NCLOB 转为字符串:

sql

复制

-- 使用 TO_CHAR(注意长度限制,超过 4000 会报错)
SELECT TO_CHAR(nclob_column) as nclob_column FROM table;

-- 或使用 DBMS_LOB.SUBSTR(可指定长度,最大 32767 字符)
SELECT DBMS_LOB.SUBSTR(nclob_column, 4000) as nclob_column FROM table;

-- 或使用 CAST
SELECT CAST(nclob_column AS VARCHAR(4000)) as nclob_column FROM table;

注意TO_CHAR 有长度限制(通常 4000 字符),超长内容会被截断或报错。


方案 3:自定义 TypeHandler(灵活但代码量大)

注册自定义的 ClobTypeHandler 处理 DmdbNClob

java

复制

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

@MappedJdbcTypes(JdbcType.CLOB)
public class DmdbNClobTypeHandler extends BaseTypeHandler<String> {
    
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) 
            throws SQLException {
        ps.setString(i, parameter);
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // 直接按 String 读取,驱动会自动处理
        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);
    }
}

然后在 MyBatis 配置中注册:

java

复制

@Configuration
public class MyBatisConfig {
    @Bean
    public ConfigurationCustomizer typeHandlerRegistry() {
        return configuration -> {
            // 注册自定义 Handler
            configuration.getTypeHandlerRegistry().register(
                Clob.class, 
                JdbcType.CLOB, 
                DmdbNClobTypeHandler.class
            );
        };
    }
}

或 XML 配置:

xml

复制

<typeHandlers>
    <typeHandler javaType="java.lang.String" jdbcType="CLOB" 
                 handler="com.yourpackage.DmdbNClobTypeHandler"/>
</typeHandlers>

方案 4:升级达梦驱动(根本解决)

检查并升级到达梦数据库最新版 JDBC 驱动,部分版本已修复此问题。


总结建议

表格

场景 推荐方案
快速解决,不修改 SQL 方案 1:URL 添加 clobAsString=1
需要精确控制长度 方案 2:SQL 中使用 DBMS_LOB.SUBSTR
需要兼容多种数据库 方案 3:自定义 TypeHandler
长期维护 方案 4:升级驱动 + 方案 1

最可能解决您当前问题的是方案 1,只需修改 JDBC URL 即可,无需改动代码和 SQL

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐