简介:面向需要在流程管理系统中落地国产数据库替换的Java/Spring Boot开发者,这份资源整理了Flowable工作流引擎与达梦8数据库集成的完整实施方案。内容涵盖环境准备、pom依赖添加、JDBC驱动配置、数据库连接串与驱动类名指定、数据源和事务管理器初始化、历史数据表创建,以及达梦8特有的异常处理、性能调优和权限安全设置等关键环节,可直接作为Spring Boot项目中接入达梦8的参考,帮助规避版本兼容、建表初始化陷阱并减少异常排查成本。资源以rar压缩包形式提供,体积约13.54MB,适合具备一定Flowable或BPM基础、正在做信创适配或国产化改造的工程师查阅。目前已有4535人学习下载,其中涉及的配置思路和集成要点对部署流程定义、启动流程实例、查询任务并完成数据库迁移有较实用的参考价值。
1. 当工作流引擎遇上国产数据库:Flowable 与达梦8 集成的第一道坎
Flowable 是 Java 生态里使用率最高的开源工作流引擎之一,BPMN、CMMN、DMN 一套全包,很多企业内部系统审批流都是拿它搭的。过去几年国产化替代推进得很快,某公司在做业务系统迁移时遇到一个棘手场景:应用侧换成了国产中间件,数据库从 MySQL 切到了达梦8,但 Flowable 引擎的几十张 ACT_ 表还在 MySQL 里趴着——流程引擎和业务表分库分家,事务没法保证,部署单点故障,领导一句话“年底前全部切完”。把 Flowable 集成到达梦8 数据库,就是这个场景下必须趟的一条路。
先说结论:Flowable 官方并没有把达梦列入支持清单,它的方言体系默认只覆盖 MySQL、Oracle、PostgreSQL、DB2 这几类,所以集成达梦8 不是“填个连接串就能跑”的事,而是要把引擎的建表、方言、类型映射、脚本执行器挨个盘一遍。好消息是达梦8 对 Oracle 兼容模式做得比较扎实,而 Flowable 对 Oracle 方言支持得很完整,这就给了我们一条实际的集成路线:让 Flowable 认为自己在连 Oracle,但底层驱动走达梦自己的 JDBC,再配合手工建表和关掉自动建表,绕开引擎内部不认达梦这个产品类型的问题。本文就把这条路线用什么版本、动哪些配置、踩哪些坑,从建库到验证一步步讲清楚。适合正在做信创适配、手里有存量 Flowable 应用要迁到达梦8 的读者,也适合还没开始、想先评估“这事到底要花多少工作量”的人。不需要你精通达梦内核,但需要你操作过 Spring Boot 项目、看过 Flowable 配置类,下面的操作才有个抓手。
2. 为什么 Flowable 官方不支持达梦:先搞懂引擎的数据库识别机制
2.1 Flowable 如何判断“我连的是什么数据库”
Flowable 启动时有个很关键的流程:它拿到数据源连接后,会通过 JDBC 的DatabaseMetaData去读数据库产品的名字和版本,然后跟自己的内部枚举做匹配。这个枚举定义了引擎支持的全部数据库类型,决定了后面的行为分支:用哪套建表脚本、用哪个方言类、是否默认开启某些特性。
在 Flowable 6.x 的源码里,这个枚举叫DB_TYPE,里面写死了MYSQL、ORACLE、POSTGRESQL、DB2、MSSQL等几个常量。引擎启动时会拿DatabaseMetaData.getDatabaseProductName()的返回值去字符串匹配,匹配上了才认为“这是支持的数据库”,往下走初始化逻辑;匹配不上,就直接抛异常或者走默认的DEFAULT分支,而默认分支的很多 SQL 语法假设是错的——比如分页语法、自增主键的获取方式、布尔类型的映射。
达梦8 的 JDBC 驱动在getDatabaseProductName()里返回的是DM DBMS(不同的驱动版本可能返回DM或达梦数据库)。这个字符串 Flowable 的枚举里没有,所以引擎会走DEFAULT分支。结果就是两件事特别闹心:一是 Flowable 启动时检测到不支持的数据库,直接报错拒绝初始化;二是即使你手动把表的建表脚本跑进去了,后续引擎做分页查询、生成 ID 时用的语法假设依然不匹配达梦的真实行为。这就是“集成”真正的难点——不是连不上,而是引擎内部不认这个产品类型。
2.2 达梦8 的 Oracle 兼容模式为什么是关键突破口
达梦8 提供了三种兼容模式:Oracle、MySQL、SQL Server,由初始化实例时的COMPATIBLE_MODE参数决定。同一套达梦库不能同时兼容多种模式,选完就固定下来了。Flowable 恰好把 Oracle 方言和 Oracle 建表脚本实现得很完整——Oracle 的表空间、序列、触发器,它都考虑到了。所以我们的集成路线就顺理成章:让达梦8 开 Oracle 兼容模式,Flowable 侧把数据库类型强行指定为 Oracle,让它用 Oracle 方言,但连接串和驱动都用达梦自己的。
有人会问“达梦的 Oracle 兼容到底兼容到什么程度”,这个问题很关键,直接决定方案敢不敢做。从我接触过的达梦8 项目看,Oracle 兼容模式主要覆盖了数据类型(VARCHAR2、NUMBER、CLOB 这些关键字直接解析)、PL/SQL 基本语法、序列、视图、同义词。但有些东西并不兼容,比如START WITH ... CONNECT BY的递归查询能力弱、物化视图不完全等价、部分内置函数靠自动改写实现。Flowable 的 Oracle 方言里用到的 SQL 特性比较基础——标准的分页写法、序列取 ID、简单的数据类型映射,我在后面的验证章节会列出具体的功能点,这些在 Oracle 兼容模式下都能正常工作。
不过这里要提醒一句:如果你们部署达梦8 的时候已经开了 MySQL 兼容模式,那下面这套方案就不成立。Flowable 的 MySQL 方言用的是 `` 反引号、AUTO_INCREMENT、LIMIT分页这些语法,达梦的 MySQL 兼容模式不一定能正确处理 Flowable 那套 MyBatis 映射文件里的写法。遇到这种情况,要么让 DBA 重新初始化一个 Oracle 兼容模式的实例,要么就放弃这套方案,考虑在达梦之上做表结构手工改造,但那样成本会高很多。
2.3 方案选型:方案A — 兼容模式 + 方言绕过 vs 方案B — 全手工表结构改造
先说方案A,也就是本文要详细展开的做法:达梦开 Oracle 兼容模式,Flowable 配置里把database-type写死为oracle,同时关掉自动建表,用 Flowable 官方的 Oracle 建表脚本手工初始化。这套方案的优点是用 Flowable 自己维护的 SQL 脚本,结构上不存在“某个字段类型在 Oracle 里合法、但达梦不认识”的问题;缺点是每次 Flowable 升级版本,要把新版本的建表脚本重新跑一遍,而且要处理ACT_GE_PROPERTY表里的版本校验(这个后面避坑章节会细讲)。
方案B是“让达梦原生支持 Flowable”的路子:不依赖 Oracle 兼容模式,而是把 Flowable 的 MySQL 建表脚本手工改写成达梦原生语法,再自定义方言类接管引擎的 SQL 生成。这个方案听起来更“正统”,但工作量是方案A的三到五倍。因为 Flowable 的 MyBatis 映射文件里有大量 XML 写死的 SQL,这些不是靠一个方言类就能全局替换的。你要改的是几十个 XML 文件里的分页语句、类型判断、序列调用。而且每次 Flowable 小版本升级,这些改动可能全部冲突。除非你们有专人长期维护,否则不建议走方案B。
我一般会建议:先花半天时间验证方案A,确认 Oracle 兼容模式下流程定义部署、实例启动、任务完成、历史查询全链路能通,再决定要不要投入做方案B的深度适配。大多数业务系统到这一步已经够了。
3. 用达梦8 的 Oracle 兼容模式建 Flowable 表:初始化脚本与关键开关
3.1 环境版本选型:确定用哪个 Flowable 版本和达梦驱动
做集成之前先把版本钉死,不然后面排查问题会非常痛苦。Flowable 我建议选 6.5.x 或 6.6.x 这个区间,原因有两个:一是这两个版本的结构和配置文件跟现在网上能找到的资料最贴近,二是它们的 Oracle 方言相对稳定,没有太多新特性依赖。如果你现在项目里用的是 Flowable 5.x,建议趁这次集成直接升级到 6.x,因为 5.x 的 MyBatis 映射文件结构和 6.x 差异较大,旧版本的 Oracle 方言对序列的支持不如 6.x 完善。
达梦8 的 JDBC 驱动包叫Dm8JdbcDriver18.jar(对应 JDK 1.8),也有的版本叫DmJdbcDriver18.jar。用 Maven 的话,达梦官方驱动并没有上传到中央仓库,所以你需要把 jar 包手动 install 到本地仓库或搭建一个私有 Nexus 服务。命令如下:
mvn install:install-file -Dfile=/opt/dm/drivers/jdbc/Dm8JdbcDriver18.jar \ -DgroupId=com.dameng \ -DartifactId=Dm8JdbcDriver18 \ -Dversion=8.1.2.192 \ -Dpackaging=jar这里-Dfile指向你从达梦安装目录里找到的驱动包路径,-Dversion建议用你们 DBA 给出的实际驱动版本号,不一定要跟我写的一样。install 到本地仓库后,项目里的坐标就固定成:
<dependency> <groupId>com.dameng</groupId> <artifactId>Dm8JdbcDriver18</artifactId> <version>8.1.2.192</version> </dependency>逻辑说明:Flowable 引擎本身只通过 JDBC 标准接口访问数据库,驱动用哪家品牌不影响引擎内部逻辑。把达梦驱动装进本地仓库,只是为了绕过中央仓库没有这个包的限制,坐标的 groupId 和 artifactId 可以按你们公司规范自定义。
3.2 达梦8 建库建用户:一个必须手工执行的初始化步骤
达梦8 安装好之后,默认会有一个SYSDBA用户。注意:Flowable 的连接账号不要直接用 SYSDBA——生产环境不允许这种授权方式,而且后面排错时会混淆权限问题。我们要创建一个独立用户,并赋予它建表的权限。
用达梦的管理工具(或者命令行disql)执行下面这段:
-- 创建用户 flowable_user,密码按实际情况修改 CREATE USER flowable_user IDENTIFIED BY "Flowable@2024"; -- 授予基础权限,RESOURCE 角色包含建表、建序列、建视图的权限 GRANT RESOURCE TO flowable_user; -- 允许该用户访问自己模式下的所有对象 GRANT UNLIMITED TABLESPACE TO flowable_user;参数说明:达梦里一个用户对应一个 Schema(模式),Flowable 建表时如果没有显式指定 Schema,表会建在当前用户同名的 Schema 下。RESOURCE角色在达梦里包含CREATE TABLE、CREATE SEQUENCE、CREATE VIEW、CREATE PROCEDURE等权限,这正好覆盖 Flowable 初始化脚本需要的全部权限。如果你发现建表脚本执行到一半报“权限不足”,第一时间检查这个角色有没有授予。
这里有一个达梦的特别之处:达梦8 有个内置的SYSDBA和SYSAUDITOR用户,默认开启;而普通用户默认情况下不允许登录,因为达梦的“登录”是一个独立的数据库对象。如果你创建完用户后连接报“用户名或密码错误”,其实不对——先用SYSDBA登录,执行下面这句把登录权限给出去:
-- 允许 flowable_user 从任意主机登录 ALTER USER flowable_user ACCOUNT LOCK; -- 如果上面锁定就不用往下走;正常情况是: ALTER USER flowable_user ACCOUNT UNLOCK;这段算是一个达梦8 特有的细节,很多从 MySQL 过来的人在这里卡住过,后面避坑章节里会再展开一次。
3.3 拿到 Flowable 初始化 SQL:不自动建表,改手工执行
Flowable 6.x 的建表脚本在发布包的database目录下,文件名是create/flowable.oracle.create.engine.sql、flowable.oracle.create.history.sql、flowable.oracle.create.identitylink.sql等——因为你选了 Oracle 兼容路线,所以选oracle前缀的脚本,不要去选mysql前缀的。
第一次执行时把三件套都跑掉:
# 以 flowable_user 连接达梦8,逐个执行建表脚本 disql flowable_user/"Flowable@2024"@localhost:5236 \ -f /opt/flowable-6.6.0/database/create/flowable.oracle.create.engine.sql disql flowable_user/"Flowable@2024"@localhost:5236 \ -f /opt/flowable-6.6.0/database/create/flowable.oracle.create.history.sql disql flowable_user/"Flowable@2024"@localhost:5236 \ -f /opt/flowable-6.6.0/database/create/flowable.oracle.create.identitylink.sql这里5236是达梦8 的默认端口,disql是达梦自带的命令行工具。执行完后可以验证一下表是否建全:
-- 查看当前模式下所有 ACT_ 开头的表 SELECT table_name FROM user_tables WHERE table_name LIKE 'ACT\_%' ESCAPE '\';正常情况会看到ACT_EVT_LOG、ACT_GE_BYTEARRAY、ACT_GE_PROPERTY、ACT_HI_ACTINST、ACT_HI_DETAIL、ACT_HI_PROCINST、ACT_HI_TASKINST、ACT_ID_*、ACT_RE_*、ACT_RU_*这些前缀的表,总数大约在 40 张左右(具体数量随版本微调)。
逻辑说明:为什么不让 Flowable 自动建表而是手工执行?因为 Flowable 的自动建表流程里,会先去查ACT_GE_PROPERTY表里的schema.version属性,验明版本号匹配才会继续;而且自动建表走的是引擎内置的Resource读取,它对达梦的 JDBC 元数据识别有问题,可能走到错误的分支。手工建表则完全绕开了这套逻辑,表结构和官方 Oracle 版本完全一致,后面配置引擎时只要跳过自动建表检查即可。
4. Flowable 连接达梦8 的配置改动:数据源、方言与两个必调开关
4.1 Spring Boot 数据源配置:驱动、URL 参数与连接池的注意事项
把达梦当普通数据源配进去是第一步。在application.yml里这样写:
spring: datasource: driver-class-name: dm.jdbc.driver.DmDriver url: jdbc:dm://localhost:5236?schema=FLOWABLE_USER&compatibleMode=oracle&characterEncoding=utf-8 username: flowable_user password: Flowable@2024这里有几个关键点。driver-class-name必须是dm.jdbc.driver.DmDriver,不是别的名字。url里的schema=FLOWABLE_USER是达梦特有的参数,如果不指定,达梦默认会去连SYSDBA模式下的表——即使你连接的用户是flowable_user也一样。这个参数建议显式写上,不然启动后报“表或视图不存在”,你会以为是脚本没跑成功。compatibleMode=oracle这个参数有些驱动版本不认,如果你验证发现驱动报“无效的参数值”,直接去掉即可——达梦的兼容模式是在实例初始化时确定的,JDBC URL 上的这个参数只是辅助声明,不写也不影响,但写上能让连接池的元数据查询结果更接近 Oracle。
连接池方面,HikariCP 默认配置下没问题,但有一个参数必须调:connection-test-query保持默认即可,达梦驱动对isValid()的支持没问题。需要留意的是maximum-pool-size,Flowable 的异步执行器(async executor)会额外占用连接,如果你的业务并发不高,maximum-pool-size配 10 就够,配太大反而容易把达梦的连接数打满。
4.2 关闭自动建表与版本校验:两个必须同时改的开关
Flowable 默认启动时会做“数据库完整性检查”,检测到表不存在就自动建表。我们手工建表是为了绕开它的检测逻辑,所以必须把自动建表关掉。在application.yml里加这一段:
flowable: database-schema-update: false check-version: false db-history-used: true async-executor-activate: false这里database-schema-update一共三个可选值:true(启动时自动建表或升级表结构)、false(不自动建表也不做版本检查)、create-drop(启动建表、关闭删表,只适合测试)。集成达梦时务必设成false。check-version是另一个隐藏很深的开关——它默认是true,启动时会去读ACT_GE_PROPERTY表里的schema.version字段,跟引擎 jar 包里的版本比对,不一致直接抛异常中止启动。
这里有个很实际的坑:你手工执行的 Oracle 建表脚本,会在ACT_GE_PROPERTY里写入一个schema.version值,它跟达梦的兼容模式没有关系,但跟 Flowable 引擎版本严格对应。比如你用 Flowable 6.6.0 的脚本建的库,后面升级到 6.7.0,check-version还开着就会启动失败。这也是我建议把check-version设成false的原因——不是因为它不重要,而是信创环境里 Flowable 版本可能随业务系统单独升级,这个校验在版本升级时会变成一个额外的拦路虎。
async-executor-activate建议集成调试阶段设为false。Flowable 的异步执行器会定时扫描 ACT_RU_JOB 表,如果异步任务很多、且达梦兼容模式的锁语义有细微差异,可能触发不必要的死锁告警。等全链路验证通过了,再按需打开。
4.3 方言指定与 MyBatis 映射覆盖:让引擎认为自己在连 Oracle
做完上面的配置,启动 Spring Boot 大概率会看到类似这样的异常:
FlowableCouldNotInitializeProcessEngineException: couldn't deduct database type from database product name 'DM DBMS'这个异常就是在第 2 章说的“引擎不认达梦产品名”。解决办法是在 Flowable 的ProcessEngineConfiguration上把databaseType直接指定为oracle。如果你用的是 Spring Boot 自动配置,可以通过实现一个ProcessEnginePlugin或者用一个@Configuration类手动创建ProcessEngineConfiguration,并在配置文件里显式声明:
@Configuration public class FlowableDamengConfig { @Bean public ProcessEngineConfigurationConfigurer processEngineConfigurationConfigurer() { return config -> { // 强制引擎把数据库当 Oracle 处理:方言、分页语法、ID 生成策略全部走 Oracle 分支 config.setDatabaseType("oracle"); // 使用 Flowable 自带的 Oracle 方言,不做自定义扩展 config.setDatabaseSchemaUpdate("false"); }; } }逻辑说明:setDatabaseType("oracle")是最关键的一行。引擎拿到这个值后,从建表检查、ID 生成、分页查询到历史数据清理,全部按 Oracle 的 SQL 规则走。达梦8 的 Oracle 兼容模式能接住这些规则,所以链路就通了。反过来,如果不设置这一行,即使前面的数据源和表都准备好了,引擎也会因为无法确认数据库类型而拒绝启动。这是一个必须写的硬配置,没有替代选项。
如果你不是用 Spring Boot 自动配置,而是手动创建引擎,对应的代码是:
ProcessEngineConfiguration config = ProcessEngineConfiguration .createStandaloneProcessEngineConfiguration(); config.setJdbcUrl("jdbc:dm://localhost:5236?schema=FLOWABLE_USER"); config.setJdbcDriver("dm.jdbc.driver.DmDriver"); config.setJdbcUsername("flowable_user"); config.setJdbcPassword("Flowable@2024"); config.setDatabaseType("oracle"); config.setDatabaseSchemaUpdate("false");注意:这里不要调用config.setJdbcDriver之外任何跟数据库产品相关的自动检测方法,老老实实把上述字段写死,越少的自动逻辑越不容易翻车。
4.4 启动验证:看一眼日志里最关键的五行
配置改完后启动应用,不要急着点流程。先找日志里这几行关键字:
FlowableHQ: Using database type 'oracle' FlowableHQ: using default password encryption algorithm FlowableEngine: Process engine default created FlowableEngine: No process engine deployment found第一行Using database type 'oracle'是关键——它说明引擎接受了你指定的方言,没有走默认分支。第三行Process engine default created说明引擎初始化成功。如果这两行之前出现couldn't deduct database type或schema version check failed,回到前面章节挨个检查配置项。
同时可以连到达梦8 执行一个简单查询,确认引擎启动后访问的是达梦而不是内存库:
SELECT name, value FROM act_ge_property WHERE name = 'schema.version';这里返回的value应该是你那个 Flowable 版本的版本号(比如6.6.0.0)。有了这行确认,说明 Flowable 已经把达梦8 当成 Oracle 在读写,集成第一步就真正落地了。
5. Flowable 跑达梦8 的常见问题与避坑记录:从启动失败到运行期告警
5.1 坑一:用户建好了却连不上——达梦的“登录”独立于用户存在
现象:用flowable_user连接达梦报DBMS_LOGIN_INVALID_USER_OR_PASSWORD,但密码确认没输错,用 SYSDBA 也能看到这个用户存在。
原因:达梦8 的“登录”(Login)是独立的数据库对象,创建用户后默认不会自动创建对应的登录。MySQL 里CREATE USER自带登录能力,达梦不是。首次接触达梦的人很容易在这里玄学排查半天。
解决:用 SYSDBA 执行:
-- 创建登录并绑定到用户 CREATE LOGIN flowable_user IDENTIFIED BY "Flowable@2024"; -- 如果登录已存在,则直接绑定 ALTER LOGIN flowable_user WITH USER = flowable_user;执行完再重启应用连接就通了。这个坑我在一个模拟项目X里踩过一次,当时排查了整整一个下午,就为了这一行登录绑定。
5.2 坑二:启动报schema version check failed——手工建表后版本号对不上
现象:Flowable 启动时日志出现类似Could not find schema version或schema version check failed的异常,引擎直接停掉。
原因:手工执行 Oracle 建表脚本建出来的库里,ACT_GE_PROPERTY表里schema.version的值是脚本里写死的,比如 6.6.0.0,但引擎 jar 包里实际期望的版本可能因为修复补丁而不同(6.6.1 就会要求 6.6.1.0)。更常遇到的情况是你执行脚本时用了旧版本目录下的 SQL,而引用的 Flowable 依赖已经是新版。
解决:这个坑不需要去改表里的版本号,直接把flowable.check-version设为false绕开即可。如果你希望保留版本校验,那就必须确保建表脚本和 Maven 依赖里的 Flowable 版本完全一致,连 patch 版本都不能差。我的建议是:在达梦集成这种非官方支持下,版本校验本身没有太多收益,关掉它,风险点转移到你自己记得在升级 Flowable 后重新执行对应的建表脚本。
5.3 坑三:ACT_GE_PROPERTY里值不对,导致流程部署成功但实例启动报错
现象:流程部署接口返回成功,但调用runtimeService.startProcessInstanceById时报类似Table 'ACT_RU_EXECUTION' doesn't exist或ORA-00942: table or view does not exist。
原因:这种情况表面像“表没建”,实际是连接到了错误的 Schema。前面第 3 章提过的schema=FLOWABLE_USER参数没配时,达梦连接默认落在SYSDBA模式,引擎去 SYSDBA 模式下找ACT_RU_EXECUTION,自然找不到。
解决:检查 JDBC URL 是否带schema参数,或者用disql登录后执行SELECT SYS_CONTEXT('USERENV','CURRENT_SCHEMA') FROM DUAL;看当前模式是不是FLOWABLE_USER。如果确实在SYSDBA模式,改 URL 加参数后重启。这个坑的特点是“部署接口正常、运行接口全挂”,容易让人去查权限而不是查连接模式,方向上跑偏。
5.4 坑四:达梦兼容模式下DISTINCT与GROUP BY的语义差异导致统计查询翻车
现象:Flowable 自带的管理接口里,历史流程实例列表分页查询偶尔报错,或者返回的行数不对劲。比如PROC_INST_ID_有重名时去重逻辑异常。
原因:达梦的 Oracle 兼容模式对SELECT DISTINCT的处理和原生 Oracle 有细微差异——当 SELECT 列里包含 CLOB 或大量列时,达梦可能直接报“不是 GROUP BY 表达式”的错误,或者返回错误结果集。Flowable 的历史查询里恰好有这种DISTINCT与多列联合查询的 SQL,于是踩中差异点。
解决:这种问题不在引擎配置层解决,而是在应用侧改写查询。常见做法是把涉及DISTINCT的查询改成GROUP BY主键字段,或者走子查询实现去重。举个实际例子,如果你们自己写了基于ACT_HI_PROCINST的统计报表,原来写:
SELECT DISTINCT PROC_DEF_ID_, COUNT(*) FROM ACT_HI_PROCINST GROUP BY PROC_DEF_ID_;可以改成:
SELECT PROC_DEF_ID_, COUNT(DISTINCT PROC_INST_ID_) FROM ACT_HI_PROCINST GROUP BY PROC_DEF_ID_;这样绕开了达梦对 DISTINCT 与聚合列同时出现的解析问题。Flowable 自己的管理接口如果也报类似错,看看是不是用了较老的引擎版本,升级到 6.6.x 之后的修复版本通常能缓解一部分。
5.5 坑五:定时任务与异步执行器导致的死锁告警
现象:开启async-executor-activate=true后,日志里频繁出现deadlock detected或lock wait timeout exceeded的告警,流程实例的定时提醒任务偶尔不触发。
原因:达梦8 的行锁粒度和 Oracle 有差异。Flowable 异步执行器在竞争同一条ACT_RU_JOB记录时,Oracle 下两个事务能比较平滑地串行,而达梦的某些隔离级别下锁等待更敏感,容易抛超时。
解决:集成阶段先保持async-executor-activate=false,把定时任务改成应用中自己调度,调用 Flowable 的managementService.executeJob(jobId)执行。等系统稳定运行一段时间,再评估要不要开异步执行器。如果确实需要它,就把async-executor-core-pool-size和async-executor-max-pool-size都调小(比如 1~2),并给数据库连接池配一个稍大的connection-timeout,缓解锁竞争的触发频率。
6. 验证清单与查询兼容改造:让流程日志和待办查询不再翻车
6.1 集成验证清单:从部署到审批全链路照着点一遍
集成做没做成,不看你启动日志有多干净,要看业务链路从头到尾能不能走通。我整理了一份验证清单,照着执行一遍比什么都有说服力。这份清单我在某跨平台系统的达梦迁移验证里用过一遍,覆盖了 Flowable 最核心的使用路径:
| 验证项 | 操作方式 | 预期结果 |
|---|---|---|
| 流程定义部署 | 调用repositoryService.createDeployment().addClasspathResource(...).deploy() | 返回部署 ID,ACT_RE_DEPLOYMENT有记录 |
| 启动流程实例 | 调用runtimeService.startProcessInstanceByKey(...) | 返回实例 ID,ACT_RU_EXECUTION有记录 |
| 完成任务 | 调用taskService.complete(taskId) | 任务走到下一步或流程结束,ACT_HI_TASKINST有记录 |
| 待办查询 | 调用taskService.createTaskQuery().taskAssignee("user1").list() | 返回正确待办列表,时间字段显示正确 |
| 历史查询 | 调用historyService.createHistoricProcessInstanceQuery().finished().list() | 返回已结束实例,分页不报错 |
| 流程图的获取 | 获取 BPMN 流程图的图片二进制 | ACT_GE_BYTEARRAY内容能正常转图片 |
| 会签/子流程 | 跑一个含会签节点的流程 | 多实例任务能正确生成和完成 |
每一行验证时,同时打开达梦的 SQL 日志(SLOG或应用侧开启 MyBatis 日志),看实际执行的 SQL 有没有异常。重点观察分页语句、序列调用这两类——它们是达梦兼容模式最容易出差异的地方。
6.2 时间字段与 CLOB 的查询兼容改造:两个最常见的运行期改造点
跑完上面清单后,大概率会遇到两个具体的运行期问题,这里提前讲改造思路。
第一个是时间字段的格式。达梦8 的 Oracle 兼容模式下,DATE类型默认返回格式受NLS_DATE_FORMAT参数影响,不同实例可能返回2024-01-01 12:00:00或01-JAN-24。Flowable 的实体映射里对Date类型的处理依赖 JDBC 驱动的getTimestamp(),一般不会出大问题,但如果你在应用里直接写 SQL 查询ACT_HI_TASKINST的CREATE_TIME_做报表,建议统一转换成字符串格式:
SELECT TO_CHAR(CREATE_TIME_, 'YYYY-MM-DD HH24:MI:SS') AS create_time_str FROM ACT_HI_TASKINST WHERE ASSIGNEE_ = 'user1';第二个是 CLOB 字段的读取。Flowable 的ACT_GE_BYTEARRAY表里BYTES_字段在 Oracle 建表脚本里是 BLOB,但在达梦兼容模式下可能被映射成 CLOB。CLOB 在 JDBC 里直接getBytes()会失败,必须走getClob()再转字符串。如果你在应用里自定义了读取流程定义附件的代码,注意这样处理:
// 读取 CLOB 字段内容并转为字节数组 Clob clob = rs.getClob("BYTES_"); String content = clob.getSubString(1, (int) clob.length()); byte[] bytes = content.getBytes(StandardCharsets.UTF_8);这两个改造点都不改引擎本身,只是在应用访问层做适配。如果你们目前没有自定义 SQL,只走 Flowable 的 API,那上面这些可以暂时不用处理,但心里有数以后碰到再说。
6.3 给后续升级留的后路:差异点记录与脚本化验证
达梦集成 Flowable 做完之后,最怕的是谁都不记得改过什么。我的习惯是建一份 README 记差异点——哪些配置跟 MySQL 环境不同、哪些 SQL 因为兼容模式改了写法、哪些开关是关闭的。再把第 6.1 节的验证清单写成一个 JUnit 集成测试类,每次升级 Flowable 版本或者达梦实例重启后,跑一遍测试类就知道有没有回归。
@Test void testFullProcessChainOnDameng() { // 部署、启动、完成、查询一次跑通 repositoryService.createDeployment() .addClasspathResource("processes/simple-approval.bpmn20.xml") .deploy(); ProcessInstance pi = runtimeService .startProcessInstanceByKey("simpleApproval"); Task task = taskService.createTaskQuery() .processInstanceId(pi.getId()) .singleResult(); taskService.complete(task.getId()); long count = historyService.createHistoricProcessInstanceQuery() .processInstanceId(pi.getId()) .finished() .count(); assertEquals(1L, count); }跑这个测试不需要额外环境,它就是你这个迁移项目能不能持续维护的底裤。有了它,后续谁再改配置、换驱动、升级引擎,都有一条快速反馈的路径,不用每次靠手动点流程去碰运气。这也是我做集成交付时比较看重的一道工序——技术验证不能录屏交差,要有可以重复执行的自动化脚本兜底。
说实话,Flowable 集成达梦8 这条路不是官方铺好的,走起来确实有些地方靠经验试错。但走通之后回头看,真正核心的改动只有三个:数据库类型指定为 Oracle、关掉自动建表和版本校验、手工执行官方 Oracle 建表脚本。其他的问题——登录绑定、CLOB、DISTINCT——都是遇到一个解一个,规律性很强。把这份经验沉淀下来,后续再有达梦环境的新项目,基本一天之内能把引擎跑起来。希望这篇笔记能帮你在国产化改造的路上少踩几个坑,顺利把流程引擎切到达梦8 上。
本文还有配套的精品资源,点击获取