# AI-FLOW 触发器在达梦数据库上启动报错修复记录 ## 修改日期:2026-06-04 ## 一、问题现象 后端服务启动时,控制台抛出 `ERROR` 日志,Spring Boot 启动过程被异常打断: ``` 2026-06-04 10:59:55.798 [main] ERROR org.jeecg.modules.airag.flow.service.a.d:78 - [AI-FLOW] 初始化定时触发器任务失败 org.springframework.dao.DataIntegrityViolationException: ### Error querying database. Cause: dm.jdbc.driver.DMException: -6105 第1 行附近出现错误: 数据类型不匹配 ### The error may exist in org/jeecg/modules/airag/flow/mapper/AiragFlowMapper.java ### The error may involve org.jeecg.modules.airag.flow.mapper.AiragFlowMapper.selectList ### The error occurred while executing a query ### SQL: SELECT id, trigger_cron FROM airag_flow WHERE (status = ? AND (trigger_cron IS NOT NULL AND trigger_cron <> ?)) ### Cause: dm.jdbc.driver.DMException: -6105 第1 行附近出现错误: 数据类型不匹配 ``` 错误链路: - `org.jeecg.modules.config.a.a.a(AiragScheduledTaskInitListener.java:28)` —— Spring 启动事件监听 - `org.jeecg.modules.airag.flow.service.a.d.initCronTasksFromDB(AiragFlowTaskServiceImpl.java:69)` —— 拉取启用 cron 的流程 - `com.baomidou.mybatisplus.extension.repository.IRepository.list` —— MyBatis-Plus 查询 ## 二、根因分析 ### 2.1 字段类型来源 `airag_flow.trigger_cron` 字段在 JeecgBoot 官方升级脚本中以 `text` 类型添加: - 文件:`jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.1_0__all_upgrade.sql` - 关键语句: ```sql ALTER TABLE `airag_flow` ADD COLUMN `trigger_cron` text NULL COMMENT 'cron定时任务触发器配置JSON' AFTER `metadata`; ``` ### 2.2 达梦数据库对 `text` 类型的处理 - MySQL 中 `text` 类型可直接与空字符串 `''` 进行 `<>` 比较; - 达梦(DM8)数据库中,`text` 实际映射为 `CLOB` 大对象类型; - 达梦不允许将 `CLOB` 类型字段直接与空字符串 `''` 使用 `<>` 操作符比较, 否则抛出 `-6105 数据类型不匹配` 错误。 - 通过 `USER_TAB_COLUMNS` 实测当前 `airag_flow.trigger_cron`: ``` DATA_TYPE = TEXT DATA_LENGTH = 2147483647 NULLABLE = Y ``` ### 2.3 触发 SQL 来源 `AiragFlowTaskServiceImpl.initCronTasksFromDB` 通过 MyBatis-Plus 的 `LambdaQueryWrapper` / `QueryWrapper` 生成 SQL: ```java wrapper.eq(AiragFlow::getStatus, "enable"); wrapper.isNotNull(AiragFlow::getTriggerCron); wrapper.ne(AiragFlow::getTriggerCron, ""); ``` 最终生成: ```sql SELECT id, trigger_cron FROM airag_flow WHERE (status = ? AND (trigger_cron IS NOT NULL AND trigger_cron <> ?)) ``` 其中 `trigger_cron <> ?` 中 `?` 绑定的是空字符串 `''`。该 SQL 在达梦上 触发了 CLOB 与空字符串比较的限制。 ## 三、解决方案 ### 3.1 方案选择 由于: 1. `airag.flow` 包对应的 `AiragFlowTaskServiceImpl`、`AiragScheduledTaskInitListener`、 `AiragFlowMapper` 属于 JeecgBoot 商业插件,未提供源码(运行时类路径下为 编译后类),无法直接修改业务代码; 2. MyBatis-Plus 的 `ne("", "")` 条件生成的 `<> ''` 属于框架行为, 强行通过 `InnerInterceptor` 改写 SQL 会增加维护成本与跨库兼容性风险; 3. `trigger_cron` 字段用途为 "cron 定时任务触发器配置 JSON", 单条记录体积很小(远小于 2000 字符)。 综合考虑,采用**数据库字段类型变更**方案:将 `trigger_cron` 由 `text`(达梦中实际为 CLOB)变更为 `varchar(2000)`, 使达梦(也兼容 MySQL)都能与空字符串直接比较。 ### 3.2 方案落实 —— 达梦标准变更流程 **达梦不允许通过 `MODIFY` 直接将 TEXT/CLOB 变更为 VARCHAR**(实测报 `-6160 数据类型的变更无效`),需采用"加新列 -> 灌数据 -> 删旧列 -> 重命名"四步走: ```sql -- 1. 新增临时 VARCHAR(2000) 列 ALTER TABLE airag_flow ADD COLUMN trigger_cron_tmp VARCHAR(2000) NULL; -- 2. 将原 TEXT 数据通过 CAST 灌入临时列 UPDATE airag_flow SET trigger_cron_tmp = CAST(trigger_cron AS VARCHAR(2000)); -- 3. 删除原 TEXT 列 ALTER TABLE airag_flow DROP COLUMN trigger_cron; -- 4. 将临时列重命名为原列名 ALTER TABLE airag_flow RENAME COLUMN trigger_cron_tmp TO trigger_cron; ``` ### 3.3 实测修复结果 修复后通过 JDBC 验证: | 验证项 | 修复前 | 修复后 | |--------|--------|--------| | 原报错 SQL:`SELECT ... WHERE trigger_cron <> ''` | 抛出 `-6105 数据类型不匹配` | **正常执行**,命中 1 条 | | `trigger_cron = ''` 查询 | 可执行 | 命中 11 条(数据一致) | | `trigger_cron IS NULL` 查询 | 可执行 | 命中 18 条(数据一致) | | `UPDATE` 行数 | - | 30 行(30 条记录数据完整保留) | > 备注:经查询 `USER_TAB_COLUMNS`,修复后 `TRIGGER_CRON` 在该视图中 > 数据类型字段仍显示为 `TEXT`(疑似达梦的元数据延迟或 TEXT 内部 > 存储为 VARCHAR 的表现),但**实际 SQL 行为已完全符合预期**, > 原报错已消除,业务查询均可正常执行。 ### 3.4 修改文件清单 | 序号 | 文件路径 | 类型 | 说明 | |:----:|----------|:----:|------| | 1 | `.docs/sql/AI-FLOW触发器兼容达梦数据库修复.sql` | 新增 | 达梦数据库手动修复 SQL(4 步变更流程 + 验证步骤) | | 2 | `.docs/20260604-AI-FLOW触发器达梦数据库兼容性修复记录.md` | 新增 | 本开发记录文档 | ### 3.5 为什么选用 `varchar(2000)` 而不是 `clob` / `text` - `clob` / `text` 在达梦中均按大对象存储,依然存在与空字符串比较的限制; - `varchar(2000)` 容量充足(cron 表达式 + 简单 JSON 配置远小于该值), 同时支持与空字符串直接比较; - `varchar` 在两个数据库(达梦 / MySQL)中行为一致,不存在跨库兼容问题。 ## 四、对其他业务的影响评估 | 影响项 | 评估结论 | |--------|----------| | AI-FLOW 业务功能 | 仅修复启动时 `initCronTasksFromDB` 的 SQL 执行,**不改变**功能逻辑 | | AI-FLOW 定时任务调度 | 修复后定时任务可正常从数据库加载并注册,**新增能力**(之前完全无法启动) | | `airag_flow` 其他字段 | 字段类型未变动,**不受影响** | | 其他表 | 未涉及,**不受影响** | | 前端 AI-FLOW 流程编排 | 前端通过 `trigger_cron` 字段写入 JSON 字符串,**不受影响** | | MySQL 环境 | MySQL 中 `text` 字段与空字符串比较正常,不存在此问题,无需处理 | ## 五、验证步骤 1. **执行 SQL**:使用达梦客户端(`disql` / `DM 管理工具` / `DBeaver`)连接到 `ZJRS_JEECG_BOOT` 模式 (`application-dm8.yml` 中配置的 schema),按 `.docs/sql/AI-FLOW触发器兼容达梦数据库修复.sql` 步骤执行; 2. **确认字段类型变更**: ```sql SELECT DATA_TYPE, DATA_LENGTH, NULLABLE FROM USER_TAB_COLUMNS WHERE TABLE_NAME = 'AIRAG_FLOW' AND COLUMN_NAME = 'TRIGGER_CRON'; ``` 3. **复现原报错 SQL**: ```sql SELECT id, trigger_cron FROM airag_flow WHERE (status = 'enable' AND (trigger_cron IS NOT NULL AND trigger_cron <> '')); ``` 预期:正常返回(不抛 `-6105`)。 4. **重启后端服务**: ```bash cd D:\我的文件\JeecgBoot-main\jeecg-boot mvn spring-boot:run -pl jeecg-module-system/jeecg-system-start ` -Dspring-boot.run.jvmArguments="-Dfile.encoding=UTF-8" ``` 5. **观察启动日志**:确认不再出现以下关键字的报错: - `AI-FLOW 初始化定时触发器任务失败` - `dm.jdbc.driver.DMException: -6105` - `数据类型不匹配` 6. **(可选)功能验证**:进入前端 AI-FLOW 流程编排页面,创建一个配置了 `cronTrigger` 的流程并保存,确认数据正常写入 `airag_flow.trigger_cron` 字段,后端能正确读取并调度执行。 ## 六、回滚方案 如修复后出现问题,可执行以下 SQL 回滚(将 `trigger_cron` 还原为 `TEXT` 类型,注意 4 步流程会产生新 CLOB 列): ```sql ALTER TABLE airag_flow ADD COLUMN trigger_cron_bak TEXT NULL; UPDATE airag_flow SET trigger_cron_bak = CAST(trigger_cron AS TEXT); ALTER TABLE airag_flow DROP COLUMN trigger_cron; ALTER TABLE airag_flow RENAME COLUMN trigger_cron_bak TO trigger_cron; ``` > ⚠️ 回滚后请勿再使用 `trigger_cron <> ''` 这类 SQL,否则会再次触发 > 同样的 `-6105` 错误。 ## 七、参考信息 - JeecgBoot 版本:3.9.2 - 数据库:达梦 DM8(`compatibleMode=oracle`) - 出错模块:`org.jeecg.modules.airag.flow`(JeecgBoot 商业插件,无源码) - MyBatis-Plus 版本:3.5.12 - 涉及 Flyway 历史脚本:`V3.9.1_0__all_upgrade.sql`(添加 `trigger_cron` 字段) - 修复实测环境:Windows 11 + JDK 17.0.4 + DmJdbcDriver18-8.1.3.140 --- ## 八、追加修复:关闭 AI 视频配音工具检测日志 ### 8.1 问题现象 启动日志中输出以下 WARN 提示,用户确认视频配音功能不需要使用: ``` 2026-06-04 11:39:14.626 [main] INFO o.j.m.a.v.service.impl.VideoGenerationServiceImpl:112 - === AI视频配音工具检测 === 2026-06-04 11:39:14.627 [main] WARN o.j.m.a.v.service.impl.VideoGenerationServiceImpl:116 - ffmpeg : 未安装,视频配音功能将不可用 2026-06-04 11:39:14.627 [main] WARN o.j.m.a.v.service.impl.VideoGenerationServiceImpl:121 - edge-tts : 未安装,视频配音功能将不可用 2026-06-04 11:39:14.627 [main] WARN o.j.m.a.v.service.impl.VideoGenerationServiceImpl:126 - 视频配音功能: 已禁用(缺少依赖工具,调用配音接口将直接返回无声视频) ``` ### 8.2 修改内容 修改文件:`jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/video/service/impl/VideoGenerationServiceImpl.java` 将 `@PostConstruct init()` 方法中的 ffmpeg/edge-tts 检测日志输出全部移除,仅保留工具路径查找逻辑(不影响后续功能判断),替换为注释 `// 视频配音功能已关闭,不再输出检测日志`。 ### 8.3 影响评估 - 视频配音功能本身未删除,`isToolsAvailable()` 仍可正常判断工具是否可用; - 仅移除启动时的日志提示,不影响其他业务逻辑; - 若后续需要重新启用配音功能,安装 ffmpeg/edge-tts 后功能自动恢复。