Quartz 的学习和使用

分布式 Quartz 的配置与 Spring 的集成使用。

初始化数据库

运行下面的(MySQL)数据库脚本,创建数据库表(先参照 quartz.properties 文件中 org.quartz.dataSource.myDS.URL属性配置的数据库名称创建数据库,这里我的数据库名称即为 quartz_scheduler)

其他数据库脚本见官网源代码(http://www.quartz-scheduler.org/downloads/)中 quartz-xxx-distribution\quartz-xxx\docs\dbTables 文件夹。

mysql.sql

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#
# 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;

配置 quartz.properties 文件

quartz.properties 文件位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#============================================================================
# Configure Main Scheduler Properties
#============================================================================

org.quartz.scheduler.instanceName: Quartz_Scheduler
org.quartz.scheduler.instanceId: AUTO

org.quartz.scheduler.skipUpdateCheck: true

#============================================================================
# Configure ThreadPool
#============================================================================

org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 5
org.quartz.threadPool.threadPriority: 5

#============================================================================
# Configure JobStore
#============================================================================

org.quartz.jobStore.misfireThreshold: 60000

org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties=false
org.quartz.jobStore.dataSource=myDS
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=true

#============================================================================
# Other Example Delegates
#============================================================================
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DB2v6Delegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DB2v7Delegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DriverDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.HSQLDBDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.MSSQLDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PointbaseDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.WebLogicDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.WebLogicOracleDelegate

#============================================================================
# Configure Datasources
#============================================================================

org.quartz.dataSource.myDS.driver: com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL: jdbc:mysql://localhost:3306/quartz_scheduler
org.quartz.dataSource.myDS.user: root
org.quartz.dataSource.myDS.password:
org.quartz.dataSource.myDS.maxConnections: 5
org.quartz.dataSource.myDS.validationQuery: select 0

#============================================================================
# Configure Plugins
#============================================================================

#org.quartz.plugin.shutdownHook.class: org.quartz.plugins.management.ShutdownHookPlugin
#org.quartz.plugin.shutdownHook.cleanShutdown: true


#org.quartz.plugin.triggHistory.class: org.quartz.plugins.history.LoggingJobHistoryPlugin

主要依赖

Maven:

1
2
3
4
5
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>

Gradle:

1
compile("org.quartz-scheduler:quartz:2.2.3")

Server 端示例代码

SchedulerJob.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import org.springframework.scheduling.quartz.QuartzJobBean;

@Getter
@Setter
public abstract class SchedulerJob extends QuartzJobBean implements java.io.Serializable {

String identify;

String group;

String description;

String cron;

Map jobDataMap;

public abstract void log();

@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println(this.identify + "--------" + this.group);
log();
}
}

让每个Job实例都继承SchedulerJob

Jdbc.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Getter
@Setter
public class Jdbc extends SchedulerJob {

public String url;

public String username;

public String password;

public String driverClassName;

public String sql;

@Override
public void log() {
JdbcUtils jdbcUtils = new JdbcUtils(url, username, password, driverClassName);
Map<String, Object> results = jdbcUtils.getJdbcTemplate().queryForMap(sql);
for (Map.Entry e : results.entrySet()) {
System.out.println(e.getKey() + " -------------- : " + e.getValue());
}
jdbcUtils.close();
}
}

WebConfig.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

@Bean
public Scheduler scheduler() {
try {
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.setJobFactory(jobFactory());
scheduler.start();
return scheduler;
} catch (SchedulerException e) {
e.printStackTrace();
return null;
}
}

@Bean
public JobFactory jobFactory() {
return new QuartzJobFactory();
}

protected class QuartzJobFactory extends PropertySettingJobFactory {

@Autowired
private AutowireCapableBeanFactory autowireCapableBeanFactory;

@Override
public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException {
Job jobInstance = super.newJob(bundle, scheduler);
autowireCapableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}

}

Quartz 与 Spring 集成 Job 如何自动注入 Spring 容器托管的对象

SchedulerJobServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Service
public class SchedulerJobServiceImpl implements SchedulerJobService {

@Autowired
private Scheduler scheduler;

@Override
public void addJob(SchedulerJob job) {
JobDetail jobDetail = JobBuilder.newJob(job.getClass())
.withIdentity(job.getIdentify(), job.getGroup())
.usingJobData(job.getJobDataMap())
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(job.getIdentify(), job.getGroup())
.withDescription(job.getDescription())
.withSchedule(CronScheduleBuilder.cronSchedule(job.getCron()))
.build();
try {
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}

@Override
public Set<JobKey> allJobs(String matcher) {
Set<JobKey> jobKeys = new HashSet<>();
try {
jobKeys = scheduler.getJobKeys(GroupMatcher.jobGroupContains(matcher));
} catch (SchedulerException e) {
e.printStackTrace();
}
return jobKeys;
}
}

SchedulerCreateController.java

1
2
3
4
5
6
7
8
9
10
11
12
@Controller
public class SchedulerCreateController {

@Autowired
private SchedulerJobService schedulerJobService;

@RequestMapping(value = "/jdbc", method = RequestMethod.POST)
public ResponseEntity jdbc(@RequestBody Jdbc job) {
schedulerJobService.addJob(job);
return ResponseEntity.ok().build();
}
}

对Job实例的其他操作

Client 端示例代码

ValueObject.java

1
2
3
4
5
6
7
8
9
10
11
public interface ValueObject<T> extends Serializable {

/**
* Value objects compare by the values of their attributes, they don't have an identity.
*
* @param other The other value object.
* @return <code>true</code> if the given value object's and this value object's attributes are the same.
*/
boolean sameValueAs(T other);

}

Jobable.java

1
2
3
4
public interface Jobable {

SchedulerJob convertToScheduler();
}

SchedulerJob.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Data
public class SchedulerJob implements ValueObject<SchedulerJob> {

protected String identify;

protected String group;

protected String cron;

protected String description;

protected Map<String, String> jobDataMap = new HashMap<>();

@Override
public boolean sameValueAs(final SchedulerJob other) {
return this.equals(other);
}
}

Jdbc.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Getter
@Setter
public class Jdbc implements Jobable {

public String url;

public String username;

public String password;

public String driverClassName;

public String sql;

@Override
public SchedulerJob convertToScheduler() {
SchedulerJob job = new SchedulerJob();
job.setIdentify("jdbc" + new Random().nextInt());
job.setGroup("jdbcs");
job.setDescription("j...d...b...c");
job.setCron("0 */1 * * * ? *");
return job;
}
}

RemoteSchedulerJobServiceImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Service
public class RemoteSchedulerJobServiceImpl implements RemoteSchedulerJobService {

@Autowired
private RestTemplate restTemplate;

@Value("${spring.quartz.server}")
private String remoteSchedulerServer;

@Override
public void addJob(SchedulerJob job) {
restTemplate.postForLocation(remoteSchedulerServer + "/jdbc", job);
}
}

JdbcJobCreateController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Controller
public class JdbcJobCreateController {

@Autowired
private RemoteSchedulerJobService remoteSchedulerJobService;

@RequestMapping(value = "/addJdbc")
public ResponseEntity addJob() {
SchedulerJob jdbcJob = new Jdbc().convertToScheduler();
Map<String, String> jobDataMap = new HashMap<>();
jobDataMap.put("url", "jdbc:mysql://localhost:3306/quartz_scheduler");
jobDataMap.put("username", "root");
jobDataMap.put("password", "");
jobDataMap.put("driverClassName", "com.mysql.jdbc.Driver");
jobDataMap.put("sql", "select job_name, job_group, description from qrtz_job_details limit 1");
jdbcJob.setJobDataMap(jobDataMap);
remoteSchedulerJobService.addJob(jdbcJob);
return ResponseEntity.ok().build();
}
}

将执行结果输入到日志中

数据库表的结构

参考:Quartz 存储与持久化 - 基于 quartz.properties 的配置

FAQ

  1. 如果启动了远程 quartz ,那么本地如果同时启动了 quartz 且使用了远程 quartz 这个数据库,这时会出现 quartz 时间戳不统一的问题。(QRTZ_SCHEDULER_STATE 表)

  2. org.quartz.JobPersistenceException: Couldn’t acquire next trigger: Field ‘SCHED_TIME’ doesn’t have a default value.

    详细信息:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    10:25:58.428 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_QuartzSchedulerThread] ERROR org.quartz.core.ErrorLogger - An error occurred while scanning for the next triggers to fire.

    org.quartz.JobPersistenceException: Couldn't acquire next trigger: Field 'SCHED_TIME' doesn't have a default value

    at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTrigger(JobStoreSupport.java:2822) ~[main/:?]

    at org.quartz.impl.jdbcjobstore.JobStoreSupport$41.execute(JobStoreSupport.java:2749) ~[main/:?]

    at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3795) ~[main/:?]

    at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTriggers(JobStoreSupport.java:2745) ~[main/:?]

    at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:264) [quartz-2.1.7.jar:?]

    Caused by: java.sql.SQLException: Field 'SCHED_TIME' doesn't have a default value

    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:963) ~[mysql-connector-java-5.1.39.jar:5.1.39]

    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3966) ~[mysql-connector-java-5.1.39.jar:5.1.39]

    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3902) ~[mysql-connector-java-5.1.39.jar:5.1.39]

    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2526) ~[mysql-connector-java-5.1.39.jar:5.1.39]

    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2673) ~[mysql-connector-java-5.1.39.jar:5.1.39]

    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2549) ~[mysql-connector-java-5.1.39.jar:5.1.39]

    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861) ~[mysql-connector-java-5.1.39.jar:5.1.39]

    at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2073) ~[mysql-connector-java-5.1.39.jar:5.1.39]

    at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2009) ~[mysql-connector-java-5.1.39.jar:5.1.39]

    at com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5098) ~[mysql-connector-java-5.1.39.jar:5.1.39]

    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1994) ~[mysql-connector-java-5.1.39.jar:5.1.39]

    at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:105) ~[c3p0-0.9.1.1.jar:0.9.1.1]

    at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.insertFiredTrigger(StdJDBCDelegate.java:2624) ~[quartz-2.1.7.jar:?]

    at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTrigger(JobStoreSupport.java:2805) ~[main/:?]

    ... 4 more

    10:27:56.133 [QuartzScheduler_org.springframework.scheduling.quartz.SchedulerFactoryBean#0-DESKTOP-DGF5RBI1489717255135_MisfireHandler] INFO org.quartz.impl.jdbcjobstore.JobStoreTX - Handling 1 trigger(s) that missed their scheduled fire-time.

    原因:使用的 jar 包版本与执行的数据库脚本不一致。

分享到:
Disqus 加载中...

如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理