Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。
Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。
Quartz是一个完全由java编写的开源作业调度框架。不要让作业调度这个术语吓着你。
尽管Quartz框架整合了许多额外功能, 但就其简易形式看,你会发现它易用得简直让人受不了!
在开发Quartz相关应用时,只要定义了Job(任务),Trigger(触发器)和Scheduler(调度器),即可实现一个定时调度能力。
其中Scheduler是Quartz中的核心,Scheduler负责管理Quartz应用运行时环境,Scheduler不是靠自己完成所有的工作,是根据Trigger的触发标准,
调用Job中的任务执行逻辑,来完成完整的定时任务调度。
Job - 定时任务内容是什么。
Trigger - 在什么时间上执行job。
Scheduler - 维护定时任务环境,并让触发器生效。
在SpringBoot中应用Quartz,需要依赖下述资源:
<!-- scheduled所属资源为spring-context-support --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <!-- Quartz坐标 --> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> <exclusions> <exclusion> <artifactId>slf4j-api</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions> </dependency> <!-- Sprng tx 坐标 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> </dependency> |
package com.bjsxt.boot.quartz;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
* 自定义Quartz中的job。
* 只需要实现Job接口中的一个方法。 execute
* 方法的功能就是定时任务的内容。
*/
public class SimpleQuartzJobDemo implements Job{
final String a = "";
// XxxService service;
// XxxPersistence dao;
// int age = 10; 不应存在的属性。临界资源,记录状态。有线程安全问题。
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("SimpleQuartzJobDemo run : " + new Date());
}
}
package com.bjsxt.test.quartz; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SimpleScheduleBuilder; import org.quartz.Trigger; import org.quartz.TriggerBuilder; import org.quartz.impl.StdSchedulerFactory; import com.bjsxt.boot.quartz.SimpleQuartzJobDemo; /** * 单纯使用Quartz,实现定时任务。 job、trigger、scheduler都是单例的。那么要注意,定义job的时候,不要定义临界资源(可写的属性)。 * 1. 定义Job类。 @see SimpleQuartzJobDemo * 2. 创建一个job任务对象。job任务对象是通过构建器Builder创建的。 * JobBuilder会根据提供的类型,来创建Job任务对象。创建的对象是一个JobDetail对象。 * JobDetail对象中封装了自定义的Job类型对象。是一个装饰器模式的实现。 * 3. 创建Trigger对象。为job对象提供一个执行的周期。 通过构建器Builder创建Trigger对象。 * 创建Trigger的时候,必须要提供一个执行任务的周期。 * 执行任务的周期,可以通过两种方式提供: * 3.1 使用SimpleScheduleBuilder提供。 * SimpleScheduleBuilder提供了最简单常用的周期时间模板。如:多少秒、多少分钟、多少小时执行一次。 * 3.2 使用CronScheduleBuilder提供。 就是通过Cron表达式提供周期时间。 * 4. 创建Scheduler。是调度器,在某个trigger满足的时候,运行哪一个job代码。 * 通过Factory创建对象。 * 5. 设置定时任务的调度。 * 6. 启动调度器 */ public class TestSimpleQuartz { public static void main(String[] args) throws SchedulerException { // 创建Job对象 JobDetail jobDetail = JobBuilder.newJob(SimpleQuartzJobDemo.class) .build(); Trigger trigger = TriggerBuilder.newTrigger() .withSchedule( SimpleScheduleBuilder.repeatSecondlyForever(2) ) .build(); Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); } }
springboot集成quartz
1:任务类
package com.bjsxt.boot.quartz; import java.util.Date; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.beans.factory.annotation.Autowired; import com.bjsxt.boot.commons.CommonsUtil4Quartz; public class SpringBootQuartzJobDemo implements Job { // 用于模拟任务中的业务对象。 也可能是数据访问对象,或其他类型的对象。 @Autowired private CommonsUtil4Quartz commonsUtil4Quartz; @Override public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("SpringBootQuartzJobDemo : " + new Date()); this.commonsUtil4Quartz.testMethod(); } }
2:模拟service层或dao层
package com.bjsxt.boot.commons; import org.springframework.stereotype.Component; @Component public class CommonsUtil4Quartz { public void testMethod(){ System.out.println("CommonsUtil4Quartz testMethod run..."); } }
3:配置类
package com.bjsxt.boot.configure; import org.quartz.CronScheduleBuilder; import org.quartz.CronTrigger; import org.quartz.spi.MutableTrigger; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.quartz.CronTriggerFactoryBean; import org.springframework.scheduling.quartz.JobDetailFactoryBean; import org.springframework.scheduling.quartz.SchedulerFactoryBean; import com.bjsxt.boot.quartz.SpringBootQuartzJobDemo; /** * 初始化类 * Quartz环境初始化。 * */ @Configuration public class QuartzConfiguration { /** * 创建Job对象。在Spring环境中,创建一个类型的对象的时候,很多情况下,都是通过FactoryBean来间接创建的。 * 如果有多个Job对象,定义多次方法。 * * 在JobDetailFactoryBean类型中,用于创建JobDetail对象的方法,其底层使用的逻辑是:Class.newInstance() * 也就是说,JobDetail对象不是通过Spring容器管理的。 * 因为Spring容器不管理JobDetail对象,那么Job中需要自动装配的属性,就无法实现自动状态。 * * 解决方案是: 将JobDetail加入到Spring容器中,让Spring容器管理JobDetail对象。 * 需要重写Factory相关代码。实现Spring容器管理JobDetail。 * @return */ @Bean public JobDetailFactoryBean initJobDetailFactoryBean(){ JobDetailFactoryBean factoryBean = new JobDetailFactoryBean(); // 提供job类型。 factoryBean.setJobClass(SpringBootQuartzJobDemo.class); return factoryBean; } /** * 管理Trigger对象 * CronTrigger - 就是Trigger的一个实现类型。 其中用于定义周期时间的是CronSchedulerBuilder * 实际上,CronTrigger是用于管理一个Cron表达式的类型。 * @param jobDetailFactoryBean - 上一个方法初始化的JobDetailFactoryBean * @return */ @Bean(name="cronTriggerFactoryBean1") public CronTriggerFactoryBean initCronTriggerFactoryBean( ){ CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean(); JobDetailFactoryBean jobDetailFactoryBean = this.initJobDetailFactoryBean(); factoryBean.setJobDetail(jobDetailFactoryBean.getObject()); factoryBean.setCronExpression("0/3 * * * * ?"); return factoryBean; } /** * 初始化Scheduler * @param cronTriggerFactoryBean - 上一个方法初始化的CronTriggerFactoryBean * @return */ @Bean public SchedulerFactoryBean initSchedulerFactoryBean( CustomJobFactory customJobFactory, CronTriggerFactoryBean[] cronTriggerFactoryBean){ SchedulerFactoryBean factoryBean = new SchedulerFactoryBean(); CronTrigger[] triggers = new CronTrigger[cronTriggerFactoryBean.length]; for(int i = 0; i < cronTriggerFactoryBean.length; i++){ triggers[i] = cronTriggerFactoryBean[i].getObject(); } // 注册触发器,一个Scheduler可以注册若干触发器。 factoryBean.setTriggers(triggers); // 为Scheduler设置JobDetail的工厂。可以覆盖掉SpringBoot提供的默认工厂,保证JobDetail中的自动装配有效。 factoryBean.setJobFactory(customJobFactory); return factoryBean; } }
4:以上代码运行会报错,因为jobDetail没有交由spring管理,所以需要重写工厂对象
并且是由加入dao或service引起的,分布式没有测试,若遇到同样的问题则可以考虑是这个原因,后面测试后补全。
package com.bjsxt.boot.configure; import org.quartz.spi.TriggerFiredBundle; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.scheduling.quartz.AdaptableJobFactory; import org.springframework.stereotype.Component; /** * 重写的工厂对象。 */ @Component public class CustomJobFactory extends AdaptableJobFactory { /** * AutowireCapableBeanFactory : 简单理解为Spring容器,是Spring容器Context的一个Bean对象管理工程。 * 可以实现自动装配逻辑,和对象创建逻辑。 * 是SpringIoC容器的一个重要组成部件。 */ @Autowired private AutowireCapableBeanFactory autowireCapableBeanFactory; @Override protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { // 通过父类型中的方法,创建JobDetail对象。 Object obj = super.createJobInstance(bundle); // 将JobDetail对象加入到Spring容器中,让Spring容器管理,并实现自动装配逻辑。 this.autowireCapableBeanFactory.autowireBean(obj); return obj; } }
package com.bjsxt.boot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling; /** * @EnableScheduling 必要 * 开启定时任务机制。 */ @SpringBootApplication @EnableScheduling public class AppStarter { public static void main(String[] args) { SpringApplication.run(AppStarter.class, args); } }
1 分布式Quartz
1.1 资源依赖
<!-- scheduled所属资源为spring-context-support --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <!-- Quartz坐标 避免jar冲突--> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> <exclusions> <exclusion> <artifactId>slf4j-api</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions> </dependency> <!-- 是Quartz中提供分布式处理的jar包。 --> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz-jobs</artifactId> <version>2.2.1</version> </dependency> <!-- Sprng tx 坐标 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> </dependency> <!-- web启动器 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--jdbc --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!--mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- druid数据库连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.9</version> </dependency> <!-- spring boot中的日志 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </dependency> |
1.2 提供全局配置文件
配置数据库连接相关信息。application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/quartz?autoReconnect=true&useUnicode=true&characterEncoding=utf-8 spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.initialSize=5 spring.datasource.minIdle=5 spring.datasource.maxActive=20 spring.datasource.maxWait=600000 spring.datasource.timeBetweenEvictionRunsMillis=600000 spring.datasource.minEvictableIdleTimeMillis=300000 spring.datasource.validationQuery=SELECT 1 spring.datasource.testWhileIdle=true spring.datasource.testOnBorrow=false spring.datasource.testOnReturn=false server.port=8080 |
1.3 提供Quartz配置信息
是为Quartz提供数据库配置信息的。什么数据库,表格的前缀 quartz.properties
# 是否使用properties作为数据存储 org.quartz.jobStore.useProperties=false # 数据库中的表格命名前缀 org.quartz.jobStore.tablePrefix = QRTZ_ # 是否是一个集群,是不是分布式的任务 org.quartz.jobStore.isClustered = true # 集群检查周期,单位毫秒。可以自定义缩短时间。 当某一个节点宕机的时候,其他节点等待多久后开始执行任务。 org.quartz.jobStore.clusterCheckinInterval = 5000 # 单位毫秒, 集群中的节点退出后,再次检查进入的时间间隔。 org.quartz.jobStore.misfireThreshold = 60000 # 事务隔离级别 org.quartz.jobStore.txIsolationLevelReadCommitted = true # 存储的事务管理类型 org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX # 使用的Delegate类型 org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate # 集群的命名,一个集群要有相同的命名。 org.quartz.scheduler.instanceName = ClusterQuartz # 节点的命名,可以自定义。 AUTO代表自动生成。 org.quartz.scheduler.instanceId= AUTO # rmi远程协议是否发布 org.quartz.scheduler.rmi.export = false # rmi远程协议代理是否创建 org.quartz.scheduler.rmi.proxy = false # 是否使用用户控制的事务环境触发执行job。 org.quartz.scheduler.wrapJobExecutionInUserTransaction = false |
任务类
package com.bjsxt.boot.quartz; import java.util.Date; import org.quartz.DisallowConcurrentExecution; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.PersistJobDataAfterExecution; import org.springframework.scheduling.quartz.QuartzJobBean; /** * 使用Spring提供的Quartz相关Job类型实现Job的定义。 * 父类型QuartzJobBean中,提供了分布式环境中任务的配置定义。 * 保证分布式环境中的任务是有效的。 */ @PersistJobDataAfterExecution // 当job执行结束,持久化job信息到数据库 @DisallowConcurrentExecution // 保证job的唯一性 public class SpringBootQuartzJobDemo extends QuartzJobBean { @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { System.out.println("SpringBootQuartzJobDemo : " + new Date()); } }
配置类
package com.bjsxt.boot.configure; import java.io.IOException; import java.util.Properties; import java.util.concurrent.Executor; import javax.sql.DataSource; import org.quartz.Scheduler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.PropertiesFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.quartz.CronTriggerFactoryBean; import org.springframework.scheduling.quartz.JobDetailFactoryBean; import org.springframework.scheduling.quartz.SchedulerFactoryBean; import com.bjsxt.boot.quartz.SpringBootQuartzJobDemo; @Configuration public class QuartzConfiguration { @Autowired private DataSource dataSource; /** * 创建调度器, 可以省略的。 * @return * @throws Exception */ @Bean public Scheduler scheduler() throws Exception { Scheduler scheduler = schedulerFactoryBean().getScheduler(); scheduler.start(); return scheduler; } /** * 创建调度器工厂bean对象。 * @return * @throws IOException */ @Bean public SchedulerFactoryBean schedulerFactoryBean() throws IOException { SchedulerFactoryBean factory = new SchedulerFactoryBean(); factory.setSchedulerName("Cluster_Scheduler"); factory.setDataSource(dataSource); factory.setApplicationContextSchedulerContextKey("applicationContext"); // 设置调度器中的线程池。 factory.setTaskExecutor(schedulerThreadPool()); // 设置触发器 factory.setTriggers(trigger().getObject()); // 设置quartz的配置信息 factory.setQuartzProperties(quartzProperties()); return factory; } /** * 读取quartz.properties配置文件的方法。 * @return * @throws IOException */ @Bean public Properties quartzProperties() throws IOException { PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean(); propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties")); // 在quartz.properties中的属性被读取并注入后再初始化对象 propertiesFactoryBean.afterPropertiesSet(); return propertiesFactoryBean.getObject(); } /** * 创建Job对象的方法。 * @return */ @Bean public JobDetailFactoryBean job() { JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean(); jobDetailFactoryBean.setJobClass(SpringBootQuartzJobDemo.class); // 是否持久化job内容 jobDetailFactoryBean.setDurability(true); // 设置是否多次请求尝试任务。 jobDetailFactoryBean.setRequestsRecovery(true); return jobDetailFactoryBean; } /** * 创建trigger factory bean对象。 * @return */ @Bean public CronTriggerFactoryBean trigger() { CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean(); cronTriggerFactoryBean.setJobDetail(job().getObject()); cronTriggerFactoryBean.setCronExpression("0/2 * * * * ?"); return cronTriggerFactoryBean; } /** * 创建一个调度器的线程池。 * @return */ @Bean public Executor schedulerThreadPool() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(15); executor.setMaxPoolSize(25); executor.setQueueCapacity(100); return executor; } }
启动类
package com.bjsxt.boot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableScheduling public class AppStarter { public static void main(String[] args) { SpringApplication.run(AppStarter.class, args); } }
若要测试分布式系统的定时任务,则复制代码,改下配置端口号就行,最后,贴一份sql
# # Quartz seems to work best with the driver mm.mysql-2.0.7-bin.jar # # PLEASE consider using mysql with innodb tables to avoid locking issues # # In your Quartz properties file, you'll need to set # org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate # DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS; DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS; DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE; DROP TABLE IF EXISTS QRTZ_LOCKS; DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS; DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS; DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS; DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS; DROP TABLE IF EXISTS QRTZ_TRIGGERS; DROP TABLE IF EXISTS QRTZ_JOB_DETAILS; DROP TABLE IF EXISTS QRTZ_CALENDARS; CREATE TABLE QRTZ_JOB_DETAILS ( SCHED_NAME VARCHAR(120) NOT NULL, JOB_NAME VARCHAR(200) NOT NULL, JOB_GROUP VARCHAR(200) 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) ); CREATE TABLE QRTZ_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR(200) NOT NULL, TRIGGER_GROUP VARCHAR(200) NOT NULL, JOB_NAME VARCHAR(200) NOT NULL, JOB_GROUP VARCHAR(200) 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(200) 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) ); CREATE TABLE QRTZ_SIMPLE_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR(200) NOT NULL, TRIGGER_GROUP VARCHAR(200) 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) ); CREATE TABLE QRTZ_CRON_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR(200) NOT NULL, TRIGGER_GROUP VARCHAR(200) NOT NULL, CRON_EXPRESSION VARCHAR(200) 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) ); CREATE TABLE QRTZ_SIMPROP_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR(200) NOT NULL, TRIGGER_GROUP VARCHAR(200) 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 NUMERIC(13,4) NULL, DEC_PROP_2 NUMERIC(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) ); CREATE TABLE QRTZ_BLOB_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR(200) NOT NULL, TRIGGER_GROUP VARCHAR(200) 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) ); CREATE TABLE QRTZ_CALENDARS ( SCHED_NAME VARCHAR(120) NOT NULL, CALENDAR_NAME VARCHAR(200) NOT NULL, CALENDAR BLOB NOT NULL, PRIMARY KEY (SCHED_NAME,CALENDAR_NAME) ); CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_GROUP VARCHAR(200) NOT NULL, PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP) ); CREATE TABLE QRTZ_FIRED_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, ENTRY_ID VARCHAR(95) NOT NULL, TRIGGER_NAME VARCHAR(200) NOT NULL, TRIGGER_GROUP VARCHAR(200) NOT NULL, INSTANCE_NAME VARCHAR(200) 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(200) NULL, JOB_GROUP VARCHAR(200) NULL, IS_NONCONCURRENT VARCHAR(1) NULL, REQUESTS_RECOVERY VARCHAR(1) NULL, PRIMARY KEY (SCHED_NAME,ENTRY_ID) ); CREATE TABLE QRTZ_SCHEDULER_STATE ( SCHED_NAME VARCHAR(120) NOT NULL, INSTANCE_NAME VARCHAR(200) NOT NULL, LAST_CHECKIN_TIME BIGINT(13) NOT NULL, CHECKIN_INTERVAL BIGINT(13) NOT NULL, PRIMARY KEY (SCHED_NAME,INSTANCE_NAME) ); CREATE TABLE QRTZ_LOCKS ( SCHED_NAME VARCHAR(120) NOT NULL, LOCK_NAME VARCHAR(40) NOT NULL, PRIMARY KEY (SCHED_NAME,LOCK_NAME) ); commit;