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
}