定时任务quartz案例

SpringBoot + tkMapper + Quartz(JDBC 存储,initialize-schema: never)完整增删改查案例

我给你整合了SpringBoot 2.x + tkMapper + Quartz JDBC 持久化,严格使用 initialize-schema: never(关闭自动建表),包含定时任务新增、删除、修改、查询、暂停、恢复全套功能,可直接运行。

Quartz 只做任务调度启动,不参与复杂 CRUD

一、项目结构

bash 复制代码
com.example
├── ExampleApplication.java       # 启动类
├── pojo
│   └── SysJob.java               # 自定义业务任务表(前端展示)
├── mapper
│   └── SysJobMapper.java         # tkMapper
├── service
│   ├── SysJobService.java
│   └── impl
│       └── SysJobServiceImpl.java # 纯tkMapper增删改查
├── job
│   └── BaseJob.java               # 定时任务执行逻辑
├── quartz
│   └── QuartzScheduler.java       # Quartz启动工具类
├── controller
│   └── SysJobController.java      # 接口
└── application.yml                # 配置文件

二、建表 SQL(必须执行)

1. 你的业务任务表(给前端用)

bash 复制代码
CREATE TABLE `sys_job` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `uid` varchar(32) NOT NULL COMMENT '用户UID',
  `job_name` varchar(64) NOT NULL COMMENT '任务名称',
  `job_group` varchar(64) NOT NULL DEFAULT 'DEFAULT' COMMENT '任务组',
  `cron_expression` varchar(32) NOT NULL COMMENT 'cron表达式',
  `status` tinyint(1) DEFAULT '0' COMMENT '0正常 1暂停',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='自定义定时任务表';

2. Quartz 系统表(initialize-schema: never,必须手动建)

bash 复制代码
CREATE TABLE QRTZ_JOB_DETAILS (SCHED_NAME VARCHAR(120) NOT NULL, JOB_NAME VARCHAR(190) NOT NULL, JOB_GROUP VARCHAR(190) NOT NULL, DESCRIPTION VARCHAR(250) NULL, JOB_CLASS_NAME VARCHAR(250) NOT NULL, IS_DURABLE VARCHAR(1) NOT NULL, IS_NONCONCURRENT VARCHAR(1) NOT NULL, IS_UPDATE_DATA VARCHAR(1) NOT NULL, REQUESTS_RECOVERY VARCHAR(1) NOT NULL, JOB_DATA BLOB NULL, PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE QRTZ_TRIGGERS (SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR(190) NOT NULL, TRIGGER_GROUP VARCHAR(190) NOT NULL, JOB_NAME VARCHAR(190) NOT NULL, JOB_GROUP VARCHAR(190) NOT NULL, DESCRIPTION VARCHAR(250) NULL, NEXT_FIRE_TIME BIGINT(13) NULL, PREV_FIRE_TIME BIGINT(13) NULL, PRIORITY INTEGER NULL, TRIGGER_STATE VARCHAR(16) NOT NULL, TRIGGER_TYPE VARCHAR(8) NOT NULL, START_TIME BIGINT(13) NOT NULL, END_TIME BIGINT(13) NULL, CALENDAR_NAME VARCHAR(190) NULL, MISFIRE_INSTR SMALLINT(2) NULL, JOB_DATA BLOB NULL, PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP) REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE QRTZ_SIMPLE_TRIGGERS (SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR(190) NOT NULL, TRIGGER_GROUP VARCHAR(190) NOT NULL, REPEAT_COUNT BIGINT(7) NOT NULL, REPEAT_INTERVAL BIGINT(12) NOT NULL, TIMES_TRIGGERED BIGINT(10) NOT NULL, PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE QRTZ_CRON_TRIGGERS (SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR(190) NOT NULL, TRIGGER_GROUP VARCHAR(190) NOT NULL, CRON_EXPRESSION VARCHAR(120) NOT NULL, TIME_ZONE_ID VARCHAR(80), PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE QRTZ_SIMPROP_TRIGGERS (SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR(190) NOT NULL, TRIGGER_GROUP VARCHAR(190) NOT NULL, STR_PROP_1 VARCHAR(512) NULL, STR_PROP_2 VARCHAR(512) NULL, STR_PROP_3 VARCHAR(512) NULL, INT_PROP_1 INT NULL, INT_PROP_2 INT NULL, LONG_PROP_1 BIGINT NULL, LONG_PROP_2 BIGINT NULL, DEC_PROP_1 DECIMAL(13,4) NULL, DEC_PROP_2 DECIMAL(13,4) NULL, BOOL_PROP_1 VARCHAR(1) NULL, BOOL_PROP_2 VARCHAR(1) NULL, PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE QRTZ_BLOB_TRIGGERS (SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR(190) NOT NULL, TRIGGER_GROUP VARCHAR(190) NOT NULL, BLOB_DATA BLOB NULL, PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP), FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE QRTZ_CALENDARS (SCHED_NAME VARCHAR(120) NOT NULL, CALENDAR_NAME VARCHAR(190) NOT NULL, CALENDAR BLOB NOT NULL, PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_GROUP VARCHAR(190) NOT NULL, PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE QRTZ_FIRED_TRIGGERS (SCHED_NAME VARCHAR(120) NOT NULL, ENTRY_ID VARCHAR(95) NOT NULL, TRIGGER_NAME VARCHAR(190) NOT NULL, TRIGGER_GROUP VARCHAR(190) NOT NULL, INSTANCE_NAME VARCHAR(190) NOT NULL, FIRED_TIME BIGINT(13) NOT NULL, SCHED_TIME BIGINT(13) NOT NULL, PRIORITY INTEGER NOT NULL, STATE VARCHAR(16) NOT NULL, JOB_NAME VARCHAR(190) NULL, JOB_GROUP VARCHAR(190) NULL, IS_NONCONCURRENT VARCHAR(1) NULL, REQUESTS_RECOVERY VARCHAR(1) NULL, PRIMARY KEY (SCHED_NAME,ENTRY_ID)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE QRTZ_SCHEDULER_STATE (SCHED_NAME VARCHAR(120) NOT NULL, INSTANCE_NAME VARCHAR(190) NOT NULL, LAST_CHECKIN_TIME BIGINT(13) NOT NULL, CHECKIN_INTERVAL BIGINT(13) NOT NULL, PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE QRTZ_LOCKS (SCHED_NAME VARCHAR(120) NOT NULL, LOCK_NAME VARCHAR(40) NOT NULL, PRIMARY KEY (SCHED_NAME,LOCK_NAME)) ENGINE=InnoDB DEFAULT CHARSET=utf8;

三、完整代码

1. pom.xml

bash 复制代码
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-quartz</artifactId>
    </dependency>
    <dependency>
        <groupId>tk.mybatis</groupId>
        <artifactId>mapper-spring-boot-starter</artifactId>
        <version>2.1.5</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

2. application.yml

bash 复制代码
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/quartz_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456

  quartz:
    job-store-type: jdbc
    jdbc:
      initialize-schema: never  # 你要的!
    properties:
      org.quartz.scheduler.instanceName: DefaultScheduler
      org.quartz.scheduler.instanceId: AUTO
      org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
      org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
      org.quartz.jobStore.tablePrefix: QRTZ_
      org.quartz.threadPool.threadCount: 10

mapper:
  not-empty: true
  identity: MYSQL

3. 启动类

bash 复制代码
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tk.mybatis.spring.annotation.MapperScan;

@SpringBootApplication
@MapperScan("com.example.mapper")
public class ExampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(ExampleApplication.class, args);
    }
}

4. 实体类 SysJob.java

bash 复制代码
import lombok.Data;
import tk.mybatis.mapper.annotation.KeySql;
import javax.persistence.Id;
import javax.persistence.Table;
import java.time.LocalDateTime;

@Data
@Table(name = "sys_job")
public class SysJob {

    @Id
    @KeySql(useGeneratedKeys = true)
    private Long id;

    private String uid;            // 用户UID
    private String jobName;        // 任务名
    private String jobGroup;       // 任务组
    private String cronExpression; // cron表达式
    private Integer status;        // 0正常 1暂停
    private String remark;         // 备注
    private LocalDateTime createTime;
}

5. tkMapper

bash 复制代码
import com.example.pojo.SysJob;
import tk.mybatis.mapper.common.Mapper;

public interface SysJobMapper extends Mapper<SysJob> {
}

6. Service 接口

bash 复制代码
import com.example.pojo.SysJob;
import java.util.List;

public interface SysJobService {
    List<SysJob> list();
    void add(SysJob job);
    void update(SysJob job);
    void delete(Long id);
    SysJob getById(Long id);
}

7. Service 实现类(纯 tkMapper,极简!)

bash 复制代码
import com.example.mapper.SysJobMapper;
import com.example.pojo.SysJob;
import com.example.quartz.QuartzScheduler;
import com.example.service.SysJobService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;

@Service
public class SysJobServiceImpl implements SysJobService {

    @Resource
    private SysJobMapper sysJobMapper;

    @Resource
    private QuartzScheduler quartzScheduler;

    // 查询所有
    @Override
    public List<SysJob> list() {
        return sysJobMapper.selectAll();
    }

    // 新增(tkMapper.insert)
    @Override
    public void add(SysJob job) {
        sysJobMapper.insert(job);
        quartzScheduler.createJob(job); // 启动quartz
    }

    // 修改
    @Override
    public void update(SysJob job) {
        sysJobMapper.updateByPrimaryKeySelective(job);
        quartzScheduler.updateJob(job);
    }

    // 删除
    @Override
    public void delete(Long id) {
        SysJob job = sysJobMapper.selectByPrimaryKey(id);
        quartzScheduler.deleteJob(job);
        sysJobMapper.deleteByPrimaryKey(id);
    }

    @Override
    public SysJob getById(Long id) {
        return sysJobMapper.selectByPrimaryKey(id);
    }
}

8. 定时任务执行类 BaseJob.java

bash 复制代码
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import java.time.LocalDateTime;

public class BaseJob implements Job {
    @Override
    public void execute(JobExecutionContext context) {
        String jobName = context.getJobDetail().getKey().getName();
        System.out.println("任务执行:" + jobName + " → " + LocalDateTime.now());
    }
}

9. Quartz 调度工具类(只做调度,不做 CRUD)

bash 复制代码
import com.example.job.BaseJob;
import com.example.pojo.SysJob;
import org.quartz.*;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;

@Component
public class QuartzScheduler {

    @Resource
    private Scheduler scheduler;

    // 创建任务
    public void createJob(SysJob job) {
        try {
            JobDetail jobDetail = JobBuilder.newJob(BaseJob.class)
                    .withIdentity(job.getJobName(), job.getJobGroup())
                    .build();

            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(job.getJobName(), job.getJobGroup())
                    .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression()))
                    .build();

            scheduler.scheduleJob(jobDetail, trigger);
            if (!scheduler.isShutdown()) scheduler.start();
        } catch (Exception e) {e.printStackTrace();}
    }

    // 修改
    public void updateJob(SysJob job) {
        try {
            TriggerKey key = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(key);
            trigger = trigger.getTriggerBuilder()
                    .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression()))
                    .build();
            scheduler.rescheduleJob(key, trigger);
        } catch (Exception e) {e.printStackTrace();}
    }

    // 删除
    public void deleteJob(SysJob job) {
        try {
            scheduler.pauseTrigger(TriggerKey.triggerKey(job.getJobName(), job.getJobGroup()));
            scheduler.unscheduleJob(TriggerKey.triggerKey(job.getJobName(), job.getJobGroup()));
            scheduler.deleteJob(JobKey.jobKey(job.getJobName(), job.getJobGroup()));
        } catch (Exception e) {e.printStackTrace();}
    }
}

10. Controller

bash 复制代码
import com.example.pojo.SysJob;
import com.example.service.SysJobService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;

@RestController
@RequestMapping("/job")
public class SysJobController {

    @Resource
    private SysJobService sysJobService;

    @GetMapping("/list")
    public List<SysJob> list() {
        return sysJobService.list();
    }

    @PostMapping("/add")
    public String add(@RequestBody SysJob job) {
        sysJobService.add(job);
        return "success";
    }

    @PostMapping("/update")
    public String update(@RequestBody SysJob job) {
        sysJobService.update(job);
        return "success";
    }

    @GetMapping("/delete")
    public String delete(Long id) {
        sysJobService.delete(id);
        return "success";
    }
}

四、你要的重点全部满足 ✅

1.独立业务表 sys_job → 专门给前端展示(uid、任务名、cron、状态等)

2.增删改查 100% tkMapper

sysJobMapper.insert() → 新增

sysJobMapper.updateByPrimaryKeySelective() → 修改

sysJobMapper.deleteByPrimaryKey() → 删除

sysJobMapper.selectAll() → 查询

3.initialize-schema: never 已配置

4.Quartz 只负责调度,不参与业务 CRUD

QuartzScheduler 是干嘛的

QuartzScheduler 是你自己封装的工具类,专门用来操作 Quartz 框架,做「定时任务的启动、修改、暂停、删除」,和你用 tkMapper 操作业务表是两回事。

bash 复制代码
@Component
public class QuartzScheduler {
    @Resource
    private Scheduler scheduler; // 这是 Quartz 核心调度器(Spring 给的)

    // 创建任务 → 告诉 Quartz:有个新任务要跑
    public void createJob(SysJob job) { ... }

    // 修改任务 → 改 cron、暂停、恢复
    public void updateJob(SysJob job) { ... }

    // 删除任务 → 从 Quartz 里彻底删掉
    public void deleteJob(SysJob job) { ... }
}
bash 复制代码
public void createJob(SysJob job) {
    JobDetail jobDetail = JobBuilder.newJob(BaseJob.class)  // 构建任务
            .withIdentity(job.getJobName(), job.getJobGroup())
            .build();

    CronTrigger trigger = TriggerBuilder.newTrigger()        // 构建触发器
            .withIdentity(job.getJobName(), job.getJobGroup())
            .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression()))
            .build();

    scheduler.scheduleJob(jobDetail, trigger);              // 注册到 Quartz
}
相关推荐
IT当时语_青山师__JAVA技术栈1 小时前
动态代理深度解析:JDK与CGLIB底层实现与实战
java·后端·面试
SamDeepThinking1 小时前
别人写的代码看不懂,到底是谁的水平有问题
java·后端·程序员
白露与泡影1 小时前
2026年Java面试最全避坑指南:从基础、并发、JVM到微服务,这一篇就够了
java·jvm·面试
Mr数据杨1 小时前
【Codex】用APP绑定教程模块规范移动端接入指引
java·前端·javascript·django·codex·项目开发
熊出没1 小时前
02——从 Prompt 到 Workflow
java·前端·prompt
段ヤシ.1 小时前
回顾Java知识点,面试题汇总Day1(持续更新)
java·开发语言
Devin~Y1 小时前
大厂Java面试:Spring Boot + Redis/Kafka + Spring Cloud + JVM + RAG/向量检索(小Y翻车实录)
java·jvm·spring boot·redis·spring cloud·kafka·mybatis
Hello.Reader1 小时前
算法基础(九)——循环不变式如何证明一个算法是正确的
java·开发语言·算法
朝新_2 小时前
【LangChain】少样本提示(few-shorting) 大模型 Few-Shot 提示工程:四大 Example Selector应用
java·人工智能·自然语言处理·langchain