基于springBoot动态配置定时任务

首页 / 新闻资讯 / 正文

场景描述:

在生产环境中,有时要临时调整定时任务时间,或者禁用/启用定时任务; 以前都是修改cron表达式后重启项目; 总是感觉这个操作有点麻烦,不够方便, 于是,想实现一个动态的配置处理!!!

功能实现:

1.代码结构:

2.代码实现:

2.1 创建定时任务配置表

CREATE TABLE `scheduled` (   `id` int(11) NOT NULL AUTO_INCREMENT,   `task_key` varchar(127) NOT NULL COMMENT '任务key值(使用bean名称)',   `name` varchar(127) DEFAULT NULL COMMENT '任务名称',   `cron` varchar(63) NOT NULL COMMENT '任务表达式',   `status` int(2) DEFAULT '0' COMMENT '状态(0.禁用; 1.启用)',   `create_time` timestamp NULL DEFAULT NULL COMMENT '创建时间',   `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',   PRIMARY KEY (`id`),   UNIQUE KEY `uniqu_task_key` (`task_key`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='定时任务配置表';

2.2 java代码

2.2.1 创建定时任务线程池

package com.yihaocard.main.scheduled.config;  import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;  /**  * @ClassName ScheduledTaskConfig  * @Description 创建定时任务线程池,初始化任务Map  * @Author lv617  * @Date 2020/9/8 10:39  * @Version 1.0  */ @Slf4j @Configuration public class ScheduledTaskConfig {      @Bean     public ThreadPoolTaskScheduler threadPoolTaskScheduler() {         log.info("创建定时任务调度线程池 start");         ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();         threadPoolTaskScheduler.setPoolSize(20);         threadPoolTaskScheduler.setThreadNamePrefix("taskExecutor-");         //用来设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean,这样这些异步任务的销毁就会先于Redis线程池的销毁。         threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);         //该方法用来设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住。         threadPoolTaskScheduler.setAwaitTerminationSeconds(60);         log.info("创建定时任务调度线程池 end");         return threadPoolTaskScheduler;     } } 

2.2.2 初始化启动定时任务

package com.yihaocard.main.scheduled.config;  import com.yihaocard.main.scheduled.ScheduledTaskService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component;  /**  * @ClassName ScheduledTaskRunner  * @Description 项目启动完毕后开启需要自启的任务  * @Author lv617  * @Date 2020/9/8 11:35  * @Version 1.0  */ @Slf4j @Component public class ScheduledTaskRunner implements ApplicationRunner {      @Autowired     private ScheduledTaskService scheduledTaskService;      /**      * 程序启动完毕后,需要自启的任务      */     @Override     public void run(ApplicationArguments applicationArguments){         log.info(" >>>>>> 项目启动完毕, 开启 => 需要自启的任务 开始!");         scheduledTaskService.initAllTask();         log.info(" >>>>>> 项目启动完毕, 开启 => 需要自启的任务 结束!");     } } 

2.2.3 定时任务状态枚举类

package com.yihaocard.main.scheduled.constant;  /**  * Created by lynn on 2018/4/17.  */ public enum ScheduledStatus {      ENABLE(0, "禁用"),     DISABLE(1, "启用");      private int code;     private String name;      ScheduledStatus(int code, String name){         this.code = code;         this.name = name;     }      public static ScheduledStatus getByCode(int code){         for (ScheduledStatus st : values()) {             if(code == st.getCode())                 return st;         }         return null;     }      public int getCode() {         return code;     }      public String getName() {         return name;     }  } 

2.2.4 定时任务公共父接口

package com.yihaocard.main.scheduled;  /**  * @ClassName ScheduledTaskJob  * @Description 创建调度任务公共父接口  * @Author lv617  * @Date 2020/9/8 10:43  * @Version 1.0  */ public interface ScheduledTaskJob extends Runnable{ } 

2.2.5 定时任务实现类(处理具体的定时任务逻辑)

注:本文档由于篇幅限制,只写两个空的实现类作为演示用;

package com.yihaocard.main.scheduled.impl;  import com.yihaocard.main.scheduled.ScheduledTaskJob; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service;  /**  * @ClassName ScheduledTaskJob01  * @Description 测试类01  * @Author lv617  * @Date 2020/9/8 10:46  * @Version 1.0  */ @Slf4j @Service public class ScheduledTaskJob01 implements ScheduledTaskJob {      @Override     public void run() {         // TODO 要处理的业务逻辑         log.info("ScheduledTask => 01  run  当前线程名称 {} ", Thread.currentThread().getName());     } } 
package com.yihaocard.main.scheduled.impl;  import com.yihaocard.main.scheduled.ScheduledTaskJob; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service;  /**  * @ClassName ScheduledTaskJob01  * @Description 测试类02  * @Author lv617  * @Date 2020/9/8 10:46  * @Version 1.0  */ @Slf4j @Service public class ScheduledTaskJob02 implements ScheduledTaskJob {      @Override     public void run() {         // TODO 要处理的业务逻辑         log.info("ScheduledTask => 02  run  当前线程名称 {} ", Thread.currentThread().getName());     } } 

2.2.6 定时任务管理接口(重要)

package com.yihaocard.main.scheduled;  import com.yihaocard.main.module.scheduled.model.Scheduled;  /**  * @ClassName ScheduledTaskService  * @Description 定时任务接口  * @Author lv617  * @Date 2020/9/8 10:51  * @Version 1.0  */ public interface ScheduledTaskService {      /**      * 根据任务key 启动任务      */     Boolean start(String taskKey, Scheduled scheduled);      /**      * 根据任务key 停止任务      */     Boolean stop(String taskKey);      /**      * 根据任务key 重启任务      */     Boolean restart(String taskKey, Scheduled scheduled);      /**      * 初始化  ==> 启动所有正常状态的任务      */     void initAllTask(); } 

2.2.7 定时任务管理实现类(重要)

package com.yihaocard.main.scheduled.impl;  import com.yihaocard.main.module.scheduled.dao.ScheduledMapper; import com.yihaocard.main.module.scheduled.model.Scheduled; import com.yihaocard.main.module.scheduled.model.ScheduledExample; import com.yihaocard.main.scheduled.ScheduledTaskJob; import com.yihaocard.main.scheduled.ScheduledTaskService; import com.yihaocard.main.scheduled.constant.ScheduledStatus; import com.yihaocard.main.springboot.SpringContext; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.TriggerContext; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.support.CronTrigger; import org.springframework.stereotype.Service;  import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.locks.ReentrantLock;  /**  * @ClassName ScheduledTaskServiceImpl  * @Description 定时任务实现  * @Author lv617  * @Date 2020/9/8 10:53  * @Version 1.0  */ @Slf4j @Service public class ScheduledTaskServiceImpl implements ScheduledTaskService {      @Value("${task.enabled}")     private Boolean taskEnable;      /**      * 可重入锁      */     private ReentrantLock lock = new ReentrantLock();     /**      * 定时任务线程池      */     @Autowired     private ThreadPoolTaskScheduler threadPoolTaskScheduler;      /**      * 存放已经启动的任务map      */     private Map<String, ScheduledFuture> scheduledFutureMap = new ConcurrentHashMap<>();      @Autowired     private ScheduledMapper scheduledMapper;      /**      * 描述: 根据任务key 启动任务      *      * @param taskKey      * @param scheduled      * @return java.lang.Boolean      * @author lv617      * @date 2020/9/24 11:16      */     @Override     public Boolean start(String taskKey, Scheduled scheduled) {         log.info(">>>>>> 启动任务 {} 开始 >>>>>>", taskKey);         //添加锁放一个线程启动,防止多人启动多次         lock.lock();         log.info(">>>>>> 添加任务启动锁完毕");         try {             //校验是否已经启动             if (this.isStart(taskKey)) {                 log.info(">>>>>> 当前任务已经启动,无需重复启动!");                 return false;             }             //查询配置             if(scheduled == null)                 scheduled = this.getByTaskKey(taskKey);             if(scheduled == null)                 return false;             //启动任务             this.doStartTask(scheduled);         } finally {             // 释放锁             lock.unlock();             log.info(">>>>>> 释放任务启动锁完毕");         }         log.info(">>>>>> 启动任务 {} 结束 >>>>>>", taskKey);         return true;     }      /**      * 描述: 查询定时任务配置参数      *      * @param taskKey      * @return com.yihaocard.main.module.scheduled.model.Scheduled      * @author lv617      * @date 2020/9/24 11:14      */     private Scheduled getByTaskKey(String taskKey) {         ScheduledExample scheduledExample = new ScheduledExample();         scheduledExample.createCriteria()                 .andStatusEqualTo(ScheduledStatus.DISABLE.getCode())                 .andTaskKeyEqualTo(taskKey);         List<Scheduled> scheduleds = scheduledMapper.selectByExample(scheduledExample);         if(scheduleds == null || scheduleds.size() < 1)             return null;         return scheduleds.get(0);     }      /**      * 描述: 根据 key 停止任务      *      * @param taskKey      * @return java.lang.Boolean      * @author lv617      * @date 2020/9/24 11:17      */     @Override     public Boolean stop(String taskKey) {         log.info(">>>>>> 进入停止任务 {}  >>>>>>", taskKey);         //当前任务实例是否存在         boolean taskStartFlag = scheduledFutureMap.containsKey(taskKey);         log.info(">>>>>> 当前任务实例是否存在 {}", taskStartFlag);         if (taskStartFlag) {             //获取任务实例             ScheduledFuture scheduledFuture = scheduledFutureMap.get(taskKey);             //关闭实例             boolean cancel = scheduledFuture.cancel(true);             log.info("cancel:{}", cancel);             //删除关闭的任务实例             scheduledFutureMap.remove(taskKey);         }         log.info(">>>>>> 结束停止任务 {}  >>>>>>", taskKey);         return taskStartFlag;     }      /**      * 描述: 根据任务key 重启任务      *      * @param taskKey      * @param scheduled      * @return java.lang.Boolean      * @author lv617      * @date 2020/9/24 11:18      */     @Override     public Boolean restart(String taskKey, Scheduled scheduled) {         log.info(">>>>>> 进入重启任务 {}  >>>>>>", taskKey);         //先停止         this.stop(taskKey);         //查询配置         if(scheduled == null)             scheduled = this.getByTaskKey(taskKey);         if(scheduled == null)             return false;         //再启动         return this.start(taskKey,scheduled);     }      /**      * 初始化  ==> 启动所有正常状态的任务      */     @Override     public void initAllTask() {         if(!taskEnable){             log.info("配置文件禁用了定时任务----");             return;         }         ScheduledExample scheduledExample = new ScheduledExample();         scheduledExample.createCriteria()                 .andStatusEqualTo(ScheduledStatus.DISABLE.getCode());         List<Scheduled> scheduleds = scheduledMapper.selectByExample(scheduledExample);         log.info("初始化  ==> 启动所有正常状态的任务开始 !size={}", scheduleds == null ? 0 : scheduleds.size());         if (scheduleds == null || scheduleds.size() < 1) {             return;         }         for (Scheduled scheduled : scheduleds) {             //任务 key             String taskKey = scheduled.getTaskKey();             //校验是否已经启动             if (this.isStart(taskKey)) {                 // 重启任务                 this.restart(taskKey,scheduled);             } else {                 // 启动任务                 this.doStartTask(scheduled);             }         }         log.info("初始化  ==> 启动所有正常状态的任务结束 !");     }      /**      * 执行启动任务      */     private void doStartTask(Scheduled scheduled) {         if (scheduled == null)             return;         //任务key         String taskKey = scheduled.getTaskKey();         //定时表达式         String taskCron = scheduled.getCron();         //获取需要定时调度的接口         ScheduledTaskJob scheduledTaskJob = (ScheduledTaskJob) SpringContext.getBean(taskKey);         log.info(">>>>>> 任务 [ {} ] ,cron={}", scheduled.getName(), taskCron);         ScheduledFuture scheduledFuture = threadPoolTaskScheduler.schedule(scheduledTaskJob, (TriggerContext triggerContext) -> new CronTrigger(taskCron).nextExecutionTime(triggerContext));         //将启动的任务放入 map         scheduledFutureMap.put(taskKey, scheduledFuture);     }      /**      * 任务是否已经启动      */     private Boolean isStart(String taskKey) {         //校验是否已经启动         if (scheduledFutureMap.containsKey(taskKey)) {             if (!scheduledFutureMap.get(taskKey).isCancelled()) {                 return true;             }         }         return false;     }  } 

3. 效果展示

3.1 定时任务初始配置

3.2 启动项目

3.3 后台管理修改定时任务

注:后台定时任务管理页面就是展示数据库scheduled表数据,提交修改就是更新数据库数据并调用ScheduledTaskService类的restart()方法,这里的简单逻辑就不在赘述了!

3.3.1 修改前

3.3.2 编辑修改

3.3.3 提交修改

至此,已完整的实现了动态的定时任务修改/重启/关闭的功能!

4. 补充Scheduled和ScheduledExample两个类

package com.yihaocard.main.module.scheduled.model;  import java.time.LocalDateTime; import lombok.Data; import lombok.experimental.Accessors;  /**  * scheduled  */ @Accessors(chain = true) @Data public class Scheduled {     /**      * scheduled.id      */     private Integer id;      /**      * scheduled.task_key      * 任务key值(使用bean名称)      */     private String taskKey;      /**      * scheduled.name      * 任务名称      */     private String name;      /**      * scheduled.cron      * 任务表达式      */     private String cron;      /**      * scheduled.status      * 状态(0.禁用; 1.启用)      */     private Integer status;      /**      * scheduled.create_time      * 创建时间      */     private LocalDateTime createTime;      /**      * scheduled.update_time      * 更新时间      */     private LocalDateTime updateTime; }
package com.yihaocard.main.module.scheduled.model;  import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List;  public class ScheduledExample {     /**      * scheduled      */     protected String orderByClause;      /**      * scheduled      */     protected boolean distinct;      /**      * scheduled      */     protected List<Criteria> oredCriteria;      /**      * This method corresponds to the database table scheduled      */     public ScheduledExample() {         oredCriteria = new ArrayList<Criteria>();     }      /**      * This method corresponds to the database table scheduled      */     public void setOrderByClause(String orderByClause) {         this.orderByClause = orderByClause;     }      /**      * This method corresponds to the database table scheduled      */     public String getOrderByClause() {         return orderByClause;     }      /**      * This method corresponds to the database table scheduled      */     public void setDistinct(boolean distinct) {         this.distinct = distinct;     }      /**      * This method corresponds to the database table scheduled      */     public boolean isDistinct() {         return distinct;     }      /**      * This method corresponds to the database table scheduled      */     public List<Criteria> getOredCriteria() {         return oredCriteria;     }      /**      * This method corresponds to the database table scheduled      */     public void or(Criteria criteria) {         oredCriteria.add(criteria);     }      /**      * This method corresponds to the database table scheduled      */     public Criteria or() {         Criteria criteria = createCriteriaInternal();         oredCriteria.add(criteria);         return criteria;     }      /**      * This method corresponds to the database table scheduled      */     public Criteria createCriteria() {         Criteria criteria = createCriteriaInternal();         if (oredCriteria.size() == 0) {             oredCriteria.add(criteria);         }         return criteria;     }      /**      * This method corresponds to the database table scheduled      */     protected Criteria createCriteriaInternal() {         Criteria criteria = new Criteria();         return criteria;     }      /**      * This method corresponds to the database table scheduled      */     public void clear() {         oredCriteria.clear();         orderByClause = null;         distinct = false;     }      /**      * This class corresponds to the database table scheduled      */     protected abstract static class GeneratedCriteria {         protected List<Criterion> criteria;          protected GeneratedCriteria() {             super();             criteria = new ArrayList<Criterion>();         }          public boolean isValid() {             return criteria.size() > 0;         }          public List<Criterion> getAllCriteria() {             return criteria;         }          public List<Criterion> getCriteria() {             return criteria;         }          protected void addCriterion(String condition) {             if (condition == null) {                 throw new RuntimeException("Value for condition cannot be null");             }             criteria.add(new Criterion(condition));         }          protected void addCriterion(String condition, Object value, String property) {             if (value == null) {                 throw new RuntimeException("Value for " + property + " cannot be null");             }             criteria.add(new Criterion(condition, value));         }          protected void addCriterion(String condition, Object value1, Object value2, String property) {             if (value1 == null || value2 == null) {                 throw new RuntimeException("Between values for " + property + " cannot be null");             }             criteria.add(new Criterion(condition, value1, value2));         }          public Criteria andIdIsNull() {             addCriterion("id is null");             return (Criteria) this;         }          public Criteria andIdIsNotNull() {             addCriterion("id is not null");             return (Criteria) this;         }          public Criteria andIdEqualTo(Integer value) {             addCriterion("id =", value, "id");             return (Criteria) this;         }          public Criteria andIdNotEqualTo(Integer value) {             addCriterion("id <>", value, "id");             return (Criteria) this;         }          public Criteria andIdGreaterThan(Integer value) {             addCriterion("id >", value, "id");             return (Criteria) this;         }          public Criteria andIdGreaterThanOrEqualTo(Integer value) {             addCriterion("id >=", value, "id");             return (Criteria) this;         }          public Criteria andIdLessThan(Integer value) {             addCriterion("id <", value, "id");             return (Criteria) this;         }          public Criteria andIdLessThanOrEqualTo(Integer value) {             addCriterion("id <=", value, "id");             return (Criteria) this;         }          public Criteria andIdIn(List<Integer> values) {             addCriterion("id in", values, "id");             return (Criteria) this;         }          public Criteria andIdNotIn(List<Integer> values) {             addCriterion("id not in", values, "id");             return (Criteria) this;         }          public Criteria andIdBetween(Integer value1, Integer value2) {             addCriterion("id between", value1, value2, "id");             return (Criteria) this;         }          public Criteria andIdNotBetween(Integer value1, Integer value2) {             addCriterion("id not between", value1, value2, "id");             return (Criteria) this;         }          public Criteria andTaskKeyIsNull() {             addCriterion("task_key is null");             return (Criteria) this;         }          public Criteria andTaskKeyIsNotNull() {             addCriterion("task_key is not null");             return (Criteria) this;         }          public Criteria andTaskKeyEqualTo(String value) {             addCriterion("task_key =", value, "taskKey");             return (Criteria) this;         }          public Criteria andTaskKeyNotEqualTo(String value) {             addCriterion("task_key <>", value, "taskKey");             return (Criteria) this;         }          public Criteria andTaskKeyGreaterThan(String value) {             addCriterion("task_key >", value, "taskKey");             return (Criteria) this;         }          public Criteria andTaskKeyGreaterThanOrEqualTo(String value) {             addCriterion("task_key >=", value, "taskKey");             return (Criteria) this;         }          public Criteria andTaskKeyLessThan(String value) {             addCriterion("task_key <", value, "taskKey");             return (Criteria) this;         }          public Criteria andTaskKeyLessThanOrEqualTo(String value) {             addCriterion("task_key <=", value, "taskKey");             return (Criteria) this;         }          public Criteria andTaskKeyLike(String value) {             addCriterion("task_key like", value, "taskKey");             return (Criteria) this;         }          public Criteria andTaskKeyNotLike(String value) {             addCriterion("task_key not like", value, "taskKey");             return (Criteria) this;         }          public Criteria andTaskKeyIn(List<String> values) {             addCriterion("task_key in", values, "taskKey");             return (Criteria) this;         }          public Criteria andTaskKeyNotIn(List<String> values) {             addCriterion("task_key not in", values, "taskKey");             return (Criteria) this;         }          public Criteria andTaskKeyBetween(String value1, String value2) {             addCriterion("task_key between", value1, value2, "taskKey");             return (Criteria) this;         }          public Criteria andTaskKeyNotBetween(String value1, String value2) {             addCriterion("task_key not between", value1, value2, "taskKey");             return (Criteria) this;         }          public Criteria andNameIsNull() {             addCriterion("name is null");             return (Criteria) this;         }          public Criteria andNameIsNotNull() {             addCriterion("name is not null");             return (Criteria) this;         }          public Criteria andNameEqualTo(String value) {             addCriterion("name =", value, "name");             return (Criteria) this;         }          public Criteria andNameNotEqualTo(String value) {             addCriterion("name <>", value, "name");             return (Criteria) this;         }          public Criteria andNameGreaterThan(String value) {             addCriterion("name >", value, "name");             return (Criteria) this;         }          public Criteria andNameGreaterThanOrEqualTo(String value) {             addCriterion("name >=", value, "name");             return (Criteria) this;         }          public Criteria andNameLessThan(String value) {             addCriterion("name <", value, "name");             return (Criteria) this;         }          public Criteria andNameLessThanOrEqualTo(String value) {             addCriterion("name <=", value, "name");             return (Criteria) this;         }          public Criteria andNameLike(String value) {             addCriterion("name like", value, "name");             return (Criteria) this;         }          public Criteria andNameNotLike(String value) {             addCriterion("name not like", value, "name");             return (Criteria) this;         }          public Criteria andNameIn(List<String> values) {             addCriterion("name in", values, "name");             return (Criteria) this;         }          public Criteria andNameNotIn(List<String> values) {             addCriterion("name not in", values, "name");             return (Criteria) this;         }          public Criteria andNameBetween(String value1, String value2) {             addCriterion("name between", value1, value2, "name");             return (Criteria) this;         }          public Criteria andNameNotBetween(String value1, String value2) {             addCriterion("name not between", value1, value2, "name");             return (Criteria) this;         }          public Criteria andCronIsNull() {             addCriterion("cron is null");             return (Criteria) this;         }          public Criteria andCronIsNotNull() {             addCriterion("cron is not null");             return (Criteria) this;         }          public Criteria andCronEqualTo(String value) {             addCriterion("cron =", value, "cron");             return (Criteria) this;         }          public Criteria andCronNotEqualTo(String value) {             addCriterion("cron <>", value, "cron");             return (Criteria) this;         }          public Criteria andCronGreaterThan(String value) {             addCriterion("cron >", value, "cron");             return (Criteria) this;         }          public Criteria andCronGreaterThanOrEqualTo(String value) {             addCriterion("cron >=", value, "cron");             return (Criteria) this;         }          public Criteria andCronLessThan(String value) {             addCriterion("cron <", value, "cron");             return (Criteria) this;         }          public Criteria andCronLessThanOrEqualTo(String value) {             addCriterion("cron <=", value, "cron");             return (Criteria) this;         }          public Criteria andCronLike(String value) {             addCriterion("cron like", value, "cron");             return (Criteria) this;         }          public Criteria andCronNotLike(String value) {             addCriterion("cron not like", value, "cron");             return (Criteria) this;         }          public Criteria andCronIn(List<String> values) {             addCriterion("cron in", values, "cron");             return (Criteria) this;         }          public Criteria andCronNotIn(List<String> values) {             addCriterion("cron not in", values, "cron");             return (Criteria) this;         }          public Criteria andCronBetween(String value1, String value2) {             addCriterion("cron between", value1, value2, "cron");             return (Criteria) this;         }          public Criteria andCronNotBetween(String value1, String value2) {             addCriterion("cron not between", value1, value2, "cron");             return (Criteria) this;         }          public Criteria andStatusIsNull() {             addCriterion("status is null");             return (Criteria) this;         }          public Criteria andStatusIsNotNull() {             addCriterion("status is not null");             return (Criteria) this;         }          public Criteria andStatusEqualTo(Integer value) {             addCriterion("status =", value, "status");             return (Criteria) this;         }          public Criteria andStatusNotEqualTo(Integer value) {             addCriterion("status <>", value, "status");             return (Criteria) this;         }          public Criteria andStatusGreaterThan(Integer value) {             addCriterion("status >", value, "status");             return (Criteria) this;         }          public Criteria andStatusGreaterThanOrEqualTo(Integer value) {             addCriterion("status >=", value, "status");             return (Criteria) this;         }          public Criteria andStatusLessThan(Integer value) {             addCriterion("status <", value, "status");             return (Criteria) this;         }          public Criteria andStatusLessThanOrEqualTo(Integer value) {             addCriterion("status <=", value, "status");             return (Criteria) this;         }          public Criteria andStatusIn(List<Integer> values) {             addCriterion("status in", values, "status");             return (Criteria) this;         }          public Criteria andStatusNotIn(List<Integer> values) {             addCriterion("status not in", values, "status");             return (Criteria) this;         }          public Criteria andStatusBetween(Integer value1, Integer value2) {             addCriterion("status between", value1, value2, "status");             return (Criteria) this;         }          public Criteria andStatusNotBetween(Integer value1, Integer value2) {             addCriterion("status not between", value1, value2, "status");             return (Criteria) this;         }          public Criteria andCreateTimeIsNull() {             addCriterion("create_time is null");             return (Criteria) this;         }          public Criteria andCreateTimeIsNotNull() {             addCriterion("create_time is not null");             return (Criteria) this;         }          public Criteria andCreateTimeEqualTo(LocalDateTime value) {             addCriterion("create_time =", value, "createTime");             return (Criteria) this;         }          public Criteria andCreateTimeNotEqualTo(LocalDateTime value) {             addCriterion("create_time <>", value, "createTime");             return (Criteria) this;         }          public Criteria andCreateTimeGreaterThan(LocalDateTime value) {             addCriterion("create_time >", value, "createTime");             return (Criteria) this;         }          public Criteria andCreateTimeGreaterThanOrEqualTo(LocalDateTime value) {             addCriterion("create_time >=", value, "createTime");             return (Criteria) this;         }          public Criteria andCreateTimeLessThan(LocalDateTime value) {             addCriterion("create_time <", value, "createTime");             return (Criteria) this;         }          public Criteria andCreateTimeLessThanOrEqualTo(LocalDateTime value) {             addCriterion("create_time <=", value, "createTime");             return (Criteria) this;         }          public Criteria andCreateTimeIn(List<LocalDateTime> values) {             addCriterion("create_time in", values, "createTime");             return (Criteria) this;         }          public Criteria andCreateTimeNotIn(List<LocalDateTime> values) {             addCriterion("create_time not in", values, "createTime");             return (Criteria) this;         }          public Criteria andCreateTimeBetween(LocalDateTime value1, LocalDateTime value2) {             addCriterion("create_time between", value1, value2, "createTime");             return (Criteria) this;         }          public Criteria andCreateTimeNotBetween(LocalDateTime value1, LocalDateTime value2) {             addCriterion("create_time not between", value1, value2, "createTime");             return (Criteria) this;         }          public Criteria andUpdateTimeIsNull() {             addCriterion("update_time is null");             return (Criteria) this;         }          public Criteria andUpdateTimeIsNotNull() {             addCriterion("update_time is not null");             return (Criteria) this;         }          public Criteria andUpdateTimeEqualTo(LocalDateTime value) {             addCriterion("update_time =", value, "updateTime");             return (Criteria) this;         }          public Criteria andUpdateTimeNotEqualTo(LocalDateTime value) {             addCriterion("update_time <>", value, "updateTime");             return (Criteria) this;         }          public Criteria andUpdateTimeGreaterThan(LocalDateTime value) {             addCriterion("update_time >", value, "updateTime");             return (Criteria) this;         }          public Criteria andUpdateTimeGreaterThanOrEqualTo(LocalDateTime value) {             addCriterion("update_time >=", value, "updateTime");             return (Criteria) this;         }          public Criteria andUpdateTimeLessThan(LocalDateTime value) {             addCriterion("update_time <", value, "updateTime");             return (Criteria) this;         }          public Criteria andUpdateTimeLessThanOrEqualTo(LocalDateTime value) {             addCriterion("update_time <=", value, "updateTime");             return (Criteria) this;         }          public Criteria andUpdateTimeIn(List<LocalDateTime> values) {             addCriterion("update_time in", values, "updateTime");             return (Criteria) this;         }          public Criteria andUpdateTimeNotIn(List<LocalDateTime> values) {             addCriterion("update_time not in", values, "updateTime");             return (Criteria) this;         }          public Criteria andUpdateTimeBetween(LocalDateTime value1, LocalDateTime value2) {             addCriterion("update_time between", value1, value2, "updateTime");             return (Criteria) this;         }          public Criteria andUpdateTimeNotBetween(LocalDateTime value1, LocalDateTime value2) {             addCriterion("update_time not between", value1, value2, "updateTime");             return (Criteria) this;         }     }      /**      * scheduled      */     public static class Criteria extends GeneratedCriteria {          protected Criteria() {             super();         }     }      /**      * This class corresponds to the database table scheduled      */     public static class Criterion {         private String condition;          private Object value;          private Object secondValue;          private boolean noValue;          private boolean singleValue;          private boolean betweenValue;          private boolean listValue;          private String typeHandler;          public String getCondition() {             return condition;         }          public Object getValue() {             return value;         }          public Object getSecondValue() {             return secondValue;         }          public boolean isNoValue() {             return noValue;         }          public boolean isSingleValue() {             return singleValue;         }          public boolean isBetweenValue() {             return betweenValue;         }          public boolean isListValue() {             return listValue;         }          public String getTypeHandler() {             return typeHandler;         }          protected Criterion(String condition) {             super();             this.condition = condition;             this.typeHandler = null;             this.noValue = true;         }          protected Criterion(String condition, Object value, String typeHandler) {             super();             this.condition = condition;             this.value = value;             this.typeHandler = typeHandler;             if (value instanceof List<?>) {                 this.listValue = true;             } else {                 this.singleValue = true;             }         }          protected Criterion(String condition, Object value) {             this(condition, value, null);         }          protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {             super();             this.condition = condition;             this.value = value;             this.secondValue = secondValue;             this.typeHandler = typeHandler;             this.betweenValue = true;         }          protected Criterion(String condition, Object value, Object secondValue) {             this(condition, value, secondValue, null);         }     } }