xxl-job集成达梦数据库
一、前言
XXL-Job 作为主流的分布式任务调度框架,默认适配 MySQL 数据库,而达梦(DM8)作为国产数据库的代表,在政企项目中广泛应用。本文将从环境准备、配置改造、SQL 适配、常见问题等维度,完整讲解 XXL-Job 与达梦数据库的整合过程(注:本文聚焦「数据库连接」环节,执行器手动注册,不包含执行器自动注册问题)。
二、环境准备
1. 基础依赖版本
| 组件 | 版本号 | 说明 |
|---|---|---|
| XXL-Job | 3.4.0-SNAPSHOT | 本文以该版本为例,适配 3.x 全系列 |
| 达梦数据库 | DM8 | 确保安装并启动 DM8 服务 |
| Spring Boot | 4.0.1 | 适配 XXL-Job Admin 底层依赖 |
| 达梦 JDBC 驱动 | 8.1.3.140 | 需匹配 DM8 服务版本 |
2. 达梦 JDBC驱动获取
通过网盘分享的文件百度网盘链接,达梦JDBC驱动

选取需要的达梦JDBC驱动
3.下载xxl-job
https://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.skip>true</maven.deploy.skip>
<dm8.jdbc.version>8.1.3.140</dm8.jdbc.version>
</properties>
<!-- 引入达梦 DM8 JDBC 驱动 -->
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmJdbcDriver18</artifactId>
<version>${dm8.jdbc.version}</version>
</dependency>
3. 数据源配置(application.properties/yaml)
3.1 修改 XXL-Job Admin 的配置文件,替换 MySQL 数据源为达梦数据源
### web
server.port=8080
server.servlet.context-path=/xxl-job-admin
### datasource-pool
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.maximum-pool-size=30
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.pool-name=HikariCP
spring.datasource.hikari.max-lifetime=600000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1
spring.datasource.hikari.validation-timeout=1000
### xxl-job, datasource
spring.datasource.url=jdbc:dm://你的IP:端口号/数据库名?schema=目标模式名&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&keepAlive=true
# 达梦 JDBC 驱动类
spring.datasource.driver-class-name=dm.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.addresses=http://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 id="saveOrUpdate" parameterType="com.xxl.job.admin.model.XxlJobLogReport" useGeneratedKeys="true" keyProperty="id" >
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)
</insert>
4.3 找到XxlJobRegistryMapper.xml的 findAll 和 registrySaveOrUpdate,改为下面的
<select id="findAll" parameterType="java.util.HashMap" resultMap="XxlJobRegistry">
SELECT <include refid="Base_Column_List" />
FROM XXL_JOB_REGISTRY t
WHERE t.UPDATE_TIME < DATEADD(SECOND, -#{timeout} , #{nowTime})
</select>
<insert id="registrySaveOrUpdate" >
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
密码:123456
2. 解决运行报表为空

示例,调用demoJob去实现实时任务
@Component
public class DemoJob {
@XxlJob("demoJob")
@TenantJob
public void execute() {
System.out.println("美滋滋");
}
}
输出美滋滋视为成功,下面开始演示
2.1 新增执行器


执行器配置:
-
AppName:(建议与业务模块相关)
-
名称:
Demo执行器(随便起,只要好认) -
注册方式:手动录入
-
机器地址: XXL-Job 执行器的服务根路径
2.2 新增任务

按我的填写就可以




成功显示

成功显示
目前只有手动注册的方式,自动注册可能因为电脑本地多网卡配置导致识别不到正确的IP地址。

3110

被折叠的 条评论
为什么被折叠?



