xxl-job集成达梦数据库一、前言XXL-Job 作为主流的分布式任务调度框架默认适配 MySQL 数据库而达梦DM8作为国产数据库的代表在政企项目中广泛应用。本文将从环境准备、配置改造、SQL 适配、常见问题等维度完整讲解 XXL-Job 与达梦数据库的整合过程注本文聚焦「数据库连接」环节执行器手动注册不包含执行器自动注册问题。二、环境准备1. 基础依赖版本组件版本号说明XXL-Job3.4.0-SNAPSHOT本文以该版本为例适配 3.x 全系列达梦数据库DM8确保安装并启动 DM8 服务Spring Boot4.0.1适配 XXL-Job Admin 底层依赖达梦 JDBC 驱动8.1.3.140需匹配 DM8 服务版本2. 达梦 JDBC驱动获取通过网盘分享的文件百度网盘链接达梦JDBC驱动选取需要的达梦JDBC驱动3.下载xxl-jobhttps://github.com/xuxueli/xxl-job.git三、核心配置改造1. 达梦数据库表结构适配1.打开目录doc下的db目录有一个数据库文件XXL-Job 官方提供的 SQL 脚本基于 MySQL 编写需适配达梦语法2.下面的sql语句能够直接运行-- -- 先删除所有表避免结构残留 -- DROP TABLE IF EXISTS XXL_JOB_LOG; DROP TABLE IF EXISTS XXL_JOB_LOGGLUE; DROP TABLE IF EXISTS XXL_JOB_INFO; DROP TABLE IF EXISTS XXL_JOB_REGISTRY; DROP TABLE IF EXISTS XXL_JOB_GROUP; DROP TABLE IF EXISTS XXL_JOB_LOG_REPORT; DROP TABLE IF EXISTS XXL_JOB_USER; DROP TABLE IF EXISTS XXL_JOB_LOCK; -- 删除可能存在的序列达梦自增优先用IDENTITY序列仅做清理 DROP SEQUENCE IF EXISTS SEQ_XXL_JOB_GROUP; DROP SEQUENCE IF EXISTS SEQ_XXL_JOB_REGISTRY; DROP SEQUENCE IF EXISTS SEQ_XXL_JOB_INFO; DROP SEQUENCE IF EXISTS SEQ_XXL_JOB_LOGGLUE; DROP SEQUENCE IF EXISTS SEQ_XXL_JOB_LOG; DROP SEQUENCE IF EXISTS SEQ_XXL_JOB_LOG_REPORT; DROP SEQUENCE IF EXISTS SEQ_XXL_JOB_USER; -- -- 重新创建所有表确保 ID 是 IDENTITY 自增列 -- -- 1. 执行器分组表 CREATE TABLE XXL_JOB_GROUP ( ID INT IDENTITY(1,1) NOT NULL COMMENT 主键ID自增, APP_NAME VARCHAR(64) NOT NULL COMMENT 执行器AppName, TITLE VARCHAR(64) NOT NULL COMMENT 执行器名称, ADDRESS_TYPE TINYINT NOT NULL DEFAULT 0 COMMENT 执行器地址类型0自动注册、1手动录入, ADDRESS_LIST VARCHAR(4000) COMMENT 执行器地址列表多地址逗号分隔, UPDATE_TIME DATETIME DEFAULT NULL, PRIMARY KEY (ID) ); -- 2. 执行器注册表 CREATE TABLE XXL_JOB_REGISTRY ( ID INT IDENTITY(1,1) NOT NULL COMMENT 主键ID自增, REGISTRY_GROUP VARCHAR(50) NOT NULL COMMENT 注册分组, REGISTRY_KEY VARCHAR(255) NOT NULL COMMENT 注册键, REGISTRY_VALUE VARCHAR(255) NOT NULL COMMENT 注册值, UPDATE_TIME DATETIME DEFAULT NULL COMMENT 更新时间, PRIMARY KEY (ID) ); CREATE UNIQUE INDEX I_G_K_V ON XXL_JOB_REGISTRY(REGISTRY_GROUP, REGISTRY_KEY, REGISTRY_VALUE); -- 3. 任务信息表重点ID 是 IDENTITY 自增列 CREATE TABLE XXL_JOB_INFO ( ID INT IDENTITY(1,1) NOT NULL COMMENT 主键ID自增, JOB_GROUP INT NOT NULL COMMENT 执行器主键ID, JOB_DESC VARCHAR(255) NOT NULL, ADD_TIME DATETIME DEFAULT NULL, UPDATE_TIME DATETIME DEFAULT NULL, AUTHOR VARCHAR(64) DEFAULT NULL COMMENT 作者, ALARM_EMAIL VARCHAR(255) DEFAULT NULL COMMENT 报警邮件, SCHEDULE_TYPE VARCHAR(50) NOT NULL DEFAULT NONE COMMENT 调度类型, SCHEDULE_CONF VARCHAR(128) DEFAULT NULL COMMENT 调度配置, MISFIRE_STRATEGY VARCHAR(50) NOT NULL DEFAULT DO_NOTHING COMMENT 调度过期策略, EXECUTOR_ROUTE_STRATEGY VARCHAR(50) DEFAULT NULL COMMENT 执行器路由策略, EXECUTOR_HANDLER VARCHAR(255) DEFAULT NULL COMMENT 执行器任务handler, EXECUTOR_PARAM VARCHAR(512) DEFAULT NULL COMMENT 执行器任务参数, EXECUTOR_BLOCK_STRATEGY VARCHAR(50) DEFAULT NULL COMMENT 阻塞处理策略, EXECUTOR_TIMEOUT INT NOT NULL DEFAULT 0 COMMENT 任务执行超时时间, EXECUTOR_FAIL_RETRY_COUNT INT NOT NULL DEFAULT 0 COMMENT 失败重试次数, GLUE_TYPE VARCHAR(50) NOT NULL COMMENT GLUE类型, GLUE_SOURCE VARCHAR(4000) COMMENT GLUE源代码, GLUE_REMARK VARCHAR(128) DEFAULT NULL COMMENT GLUE备注, GLUE_UPDATETIME DATETIME DEFAULT NULL COMMENT GLUE更新时间, CHILD_JOBID VARCHAR(255) DEFAULT NULL COMMENT 子任务ID, TRIGGER_STATUS TINYINT NOT NULL DEFAULT 0 COMMENT 调度状态0-停止1-运行, TRIGGER_LAST_TIME BIGINT NOT NULL DEFAULT 0 COMMENT 上次调度时间, TRIGGER_NEXT_TIME BIGINT NOT NULL DEFAULT 0 COMMENT 下次调度时间, PRIMARY KEY (ID) ); -- 4. GLUE日志表 CREATE TABLE XXL_JOB_LOGGLUE ( ID INT IDENTITY(1,1) NOT NULL COMMENT 主键ID自增, JOB_ID INT NOT NULL COMMENT 任务主键ID, GLUE_TYPE VARCHAR(50) DEFAULT NULL COMMENT GLUE类型, GLUE_SOURCE VARCHAR(4000) COMMENT GLUE源代码, GLUE_REMARK VARCHAR(128) NOT NULL COMMENT GLUE备注, ADD_TIME DATETIME DEFAULT NULL, UPDATE_TIME DATETIME DEFAULT NULL, PRIMARY KEY (ID) ); -- 5. 任务日志表 CREATE TABLE XXL_JOB_LOG ( ID BIGINT IDENTITY(1,1) NOT NULL COMMENT 主键ID自增, JOB_GROUP INT NOT NULL COMMENT 执行器主键ID, JOB_ID INT NOT NULL COMMENT 任务主键ID, EXECUTOR_ADDRESS VARCHAR(255) DEFAULT NULL COMMENT 执行器地址, EXECUTOR_HANDLER VARCHAR(255) DEFAULT NULL COMMENT 执行器任务handler, EXECUTOR_PARAM VARCHAR(512) DEFAULT NULL COMMENT 执行器任务参数, EXECUTOR_SHARDING_PARAM VARCHAR(20) DEFAULT NULL COMMENT 执行器分片参数, EXECUTOR_FAIL_RETRY_COUNT INT NOT NULL DEFAULT 0 COMMENT 失败重试次数, TRIGGER_TIME DATETIME DEFAULT NULL COMMENT 调度时间, TRIGGER_CODE INT NOT NULL COMMENT 调度结果, TRIGGER_MSG VARCHAR(4000) COMMENT 调度日志, HANDLE_TIME DATETIME DEFAULT NULL COMMENT 执行时间, HANDLE_CODE INT NOT NULL COMMENT 执行结果, HANDLE_MSG VARCHAR(4000) COMMENT 执行日志, ALARM_STATUS TINYINT NOT NULL DEFAULT 0 COMMENT 告警状态, PRIMARY KEY (ID) ); CREATE INDEX I_TRIGGER_TIME ON XXL_JOB_LOG(TRIGGER_TIME); CREATE INDEX I_HANDLE_CODE ON XXL_JOB_LOG(HANDLE_CODE); CREATE INDEX I_JOBID_JOBGROUP ON XXL_JOB_LOG(JOB_ID,JOB_GROUP); CREATE INDEX I_JOB_ID ON XXL_JOB_LOG(JOB_ID); -- 6. 任务日志报表 CREATE TABLE XXL_JOB_LOG_REPORT ( ID INT IDENTITY(1,1) NOT NULL COMMENT 主键ID自增, TRIGGER_DAY DATETIME DEFAULT NULL COMMENT 调度日期, RUNNING_COUNT INT NOT NULL DEFAULT 0 COMMENT 运行中数量, SUC_COUNT INT NOT NULL DEFAULT 0 COMMENT 成功数量, FAIL_COUNT INT NOT NULL DEFAULT 0 COMMENT 失败数量, UPDATE_TIME DATETIME DEFAULT NULL, PRIMARY KEY (ID) ); CREATE UNIQUE INDEX I_TRIGGER_DAY ON XXL_JOB_LOG_REPORT(TRIGGER_DAY); -- 7. 锁表 CREATE TABLE XXL_JOB_LOCK ( LOCK_NAME VARCHAR(50) NOT NULL COMMENT 锁名称, PRIMARY KEY (LOCK_NAME) ); -- 8. 用户表 CREATE TABLE XXL_JOB_USER ( ID INT IDENTITY(1,1) NOT NULL COMMENT 主键ID自增, USERNAME VARCHAR(50) NOT NULL COMMENT 账号, PASSWORD VARCHAR(100) NOT NULL COMMENT 密码, TOKEN VARCHAR(100) DEFAULT NULL COMMENT 登录token, ROLE TINYINT NOT NULL COMMENT 角色0-普通用户、1-管理员, PERMISSION VARCHAR(255) DEFAULT NULL COMMENT 权限, PRIMARY KEY (ID) ); CREATE UNIQUE INDEX I_USERNAME ON XXL_JOB_USER(USERNAME); -- -- 插入初始化数据无 ID 字段自增列自动生成 -- INSERT INTO XXL_JOB_GROUP(APP_NAME, TITLE, ADDRESS_TYPE, ADDRESS_LIST, UPDATE_TIME) VALUES (xxl-job-executor-sample, 通用执行器Sample, 0, , SYSDATE), (xxl-job-executor-sample-ai, AI执行器Sample, 0, , SYSDATE); INSERT INTO XXL_JOB_INFO(JOB_GROUP, JOB_DESC, ADD_TIME, UPDATE_TIME, AUTHOR, ALARM_EMAIL, SCHEDULE_TYPE, SCHEDULE_CONF, MISFIRE_STRATEGY, EXECUTOR_ROUTE_STRATEGY, EXECUTOR_HANDLER, EXECUTOR_PARAM, EXECUTOR_BLOCK_STRATEGY, EXECUTOR_TIMEOUT, EXECUTOR_FAIL_RETRY_COUNT, GLUE_TYPE, GLUE_SOURCE, GLUE_REMARK, GLUE_UPDATETIME, CHILD_JOBID, TRIGGER_STATUS, TRIGGER_LAST_TIME, TRIGGER_NEXT_TIME) VALUES (1, 示例任务01, SYSDATE, SYSDATE, XXL, , CRON, 0 0 0 * * ? *, DO_NOTHING, FIRST, demoJobHandler, , SERIAL_EXECUTION, 0, 0, BEAN, , GLUE代码初始化, SYSDATE, , 0, 0, 0), (2, Ollama示例任务01, SYSDATE, SYSDATE, XXL, , NONE, , DO_NOTHING, FIRST, ollamaJobHandler, { input: 慢SQL问题分析思路, prompt: 你是一个研发工程师擅长解决技术类问题。, model: qwen3:0.6b }, SERIAL_EXECUTION, 0, 0, BEAN, , GLUE代码初始化, SYSDATE, , 0, 0, 0), (2, Dify示例任务, SYSDATE, SYSDATE, XXL, , NONE, , DO_NOTHING, FIRST, difyWorkflowJobHandler, { inputs:{ input:查询班级各学科前三名 }, user: xxl-job, baseUrl: http://localhost/v1, apiKey: app-OUVgNUOQRIMokfmuJvBJoUTN }, SERIAL_EXECUTION, 0, 0, BEAN, , GLUE代码初始化, SYSDATE, , 0, 0, 0); INSERT INTO XXL_JOB_USER(USERNAME, PASSWORD, ROLE, PERMISSION) VALUES (admin, 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92, 1, ); INSERT INTO XXL_JOB_LOCK (LOCK_NAME) VALUES (schedule_lock); COMMIT; DROP SEQUENCE IF EXISTS SEQ_XXL_JOB_GROUP; DROP SEQUENCE IF EXISTS SEQ_XXL_JOB_REGISTRY; DROP SEQUENCE IF EXISTS SEQ_XXL_JOB_INFO; DROP SEQUENCE IF EXISTS SEQ_XXL_JOB_LOGGLUE; DROP SEQUENCE IF EXISTS SEQ_XXL_JOB_LOG; DROP SEQUENCE IF EXISTS SEQ_XXL_JOB_LOG_REPORT; DROP SEQUENCE IF EXISTS SEQ_XXL_JOB_USER;文件里面报错是正常的直接运行即可2. Pom.xml 依赖调整在 XXL-Job Admin 模块的 pom.xml 中替换 MySQL 驱动为达梦驱动并引入达梦 JDBC 依赖properties maven.deploy.skiptrue/maven.deploy.skip dm8.jdbc.version8.1.3.140/dm8.jdbc.version /properties !-- 引入达梦 DM8 JDBC 驱动 -- dependency groupIdcom.dameng/groupId artifactIdDmJdbcDriver18/artifactId version${dm8.jdbc.version}/version /dependency3. 数据源配置application.properties/yaml3.1 修改 XXL-Job Admin 的配置文件替换 MySQL 数据源为达梦数据源### web server.port8080 server.servlet.context-path/xxl-job-admin ### datasource-pool spring.datasource.typecom.zaxxer.hikari.HikariDataSource spring.datasource.hikari.minimum-idle10 spring.datasource.hikari.maximum-pool-size30 spring.datasource.hikari.auto-committrue spring.datasource.hikari.idle-timeout300000 spring.datasource.hikari.pool-nameHikariCP spring.datasource.hikari.max-lifetime600000 spring.datasource.hikari.connection-timeout30000 spring.datasource.hikari.connection-test-querySELECT 1 spring.datasource.hikari.validation-timeout1000 ### xxl-job, datasource spring.datasource.urljdbc:dm://你的IP:端口号/数据库名?schema目标模式名useUnicodetruecharacterEncodingUTF-8autoReconnecttruekeepAlivetrue # 达梦 JDBC 驱动类 spring.datasource.driver-class-namedm.jdbc.driver.DmDriver spring.datasource.username账号 spring.datasource.password密码 ### xxl-job, access token xxl.job.accessToken需要与你的XXL-JOB 执行器一致3.2 修改xxl-job-executor-sample-springboot的配置文件### xxl-job admin address list, such as http://address or http://address01,http://address02 ###XXL-JOB 调度中心Admin的服务地址。 xxl.job.admin.addresseshttp://192.168.85.1:8080/xxl-job-admin ### xxl-job access token xxl.job.admin.accessToken需要与你的Admin文件下的一致4.修改admin下的所有mapper文件4.1 把所有的mapper文件用单引号引用的把单引号都去掉4.2 找到XxlJobLogReportMapper.xml的saveOrUpdate改为下面的insert idsaveOrUpdate parameterTypecom.xxl.job.admin.model.XxlJobLogReport useGeneratedKeystrue keyPropertyid MERGE INTO xxl_job_log_report t USING ( SELECT #{triggerDay} AS trigger_day, #{runningCount} AS running_count, #{sucCount} AS suc_count, #{failCount} AS fail_count FROM DUAL ) s ON (t.trigger_day s.trigger_day) WHEN MATCHED THEN UPDATE SET t.running_count s.running_count, t.suc_count s.suc_count, t.fail_count s.fail_count WHEN NOT MATCHED THEN INSERT (trigger_day, running_count, suc_count, fail_count, update_time) VALUES (s.trigger_day, s.running_count, s.suc_count, s.fail_count, SYSDATE) /insert4.3 找到XxlJobRegistryMapper.xml的 findAll 和 registrySaveOrUpdate改为下面的select idfindAll parameterTypejava.util.HashMap resultMapXxlJobRegistry SELECT include refidBase_Column_List / FROM XXL_JOB_REGISTRY t WHERE t.UPDATE_TIME lt; DATEADD(SECOND, -#{timeout} , #{nowTime}) /select insert idregistrySaveOrUpdate MERGE INTO xxl_job_registry t USING ( SELECT #{registryGroup} AS registry_group, #{registryKey} AS registry_key, #{registryValue} AS registry_value, #{updateTime} AS update_time FROM dual ) s ON (t.registry_group s.registry_group AND t.registry_key s.registry_key AND t.registry_value s.registry_value) WHEN MATCHED THEN UPDATE SET t.update_time s.update_time WHEN NOT MATCHED THEN INSERT (registry_group, registry_key, registry_value, update_time) VALUES (s.registry_group, s.registry_key, s.registry_value, s.update_time); /insert四、启动1. 访问路径http://127.0.0.1:8080/xxl-job-admin账号admin密码1234562. 解决运行报表为空示例调用demoJob去实现实时任务Component public class DemoJob { XxlJob(demoJob) TenantJob public void execute() { System.out.println(美滋滋); } }输出美滋滋视为成功下面开始演示2.1 新增执行器执行器配置AppName建议与业务模块相关名称Demo执行器随便起只要好认注册方式手动录入机器地址 XXL-Job 执行器的服务根路径2.2 新增任务按我的填写就可以成功显示成功显示目前只有手动注册的方式自动注册可能因为电脑本地多网卡配置导致识别不到正确的IP地址。