问题:配置持久化方式:JobStoreCMT,事务不生效。
现象:
利用spring集成quartz进行定时任务管理,持久化配置:
org.quartz.jobStore.class:org.springframework.scheduling.quartz.LocalDataSourceJobStore
修改定时任务corn表达式时,由于corn表达式过长,超过数据库列长度限制,从而导致更新corn表达式失败,当再次更新时,会出现空指针异常。
完整配置如下:
spring:
application:
name: spring-test
quartz:
job-store-type: jdbc
properties:
org:
quartz:
scheduler:
instanceId: AUTO
jobStore:
class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
useProperties: false
tablePrefix: QRTZ_
misfireThreshold: 60000
clusterCheckinInterval: 20000
isClustered: true
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
原因:
由于quartz持久化方式是LocalDataSourceJobStore,LocalDataSourceJobStore是JobStoreCMT的子类,那么quartz不会自己管理事务。而增加定时任务,更新corn表达式等操作,quartz会涉及三张表的修改:(存储corn表达式信息,注册名称以及注册组名)、QRTZ_TRIGGERS(注册信息)、QRTZ_JOB_DETAILS(任务信息)。上述现象,由于更新corn表达式失败,第一次更新时,会将QRTZ_CORN_TRIGGERS表中原有信息删除,再次写入新信息,而删除之后,再次写入时出现异常,导致QRTZ_CORN_TRIGGERS表中无空。当再次更新信息时,会检索trigger信息,会从QRTZ_CORN_TRIGGERS表中查询,而此时该表中已无信息,从而导致空指针异常。
解决方式:
该问题涉及俩个问题,第一个:QRTZ_CORN_TRIGGERS表中列CORN_EXPRESSION长度限制,第二个问题:事务不生效,导致出现异常时未能回滚。
- 修改QRTZ_CORN_TRIGGERS长度限制;
- 事务生效。
事务生效:
a): 使用spring事务,在调用方法上添加声明式事务:@Transactional
示例:
public class MyQuartzConfig {
@Autowired
private Scheduler scheduler;
@Transactional // 加上事务注解即可解决问题
public void init() {
scheduler.scheduleJob(job, trigger);
}
}
b): 使用JobStoreTX持久化方式,让quratz自己管理事务,配置如下:
持久化配置(存储方式使用JobStoreTX,也就是数据库)
org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX
#数据库中quartz表的表名前缀
org.quartz.jobStore.tablePrefix:qrtz_
#配置连接数据源
org.quartz.jobStore.dataSource:myQuartzDB
#是否使用集群(如果项目只部署到 一台服务器,就不用了)
org.quartz.jobStore.isClustered = true
#============================================================================
# Configure Datasources配置数据源
(可被覆盖,如果在schedulerFactoryBean指定数据源)
#============================================================================
org.quartz.dataSource.myQuartzDB.driver:com.mysql.jdbc.Driver
org.quartz.dataSource.myQuartzDB.URL:jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8
org.quartz.dataSource.myQuartzDB.user:root
org.quartz.dataSource.myQuartzDB.password:root123
org.quartz.dataSource.myQuartzDB.maxConnections:10
spring配置:
spring:
application:
name: spring-test
quartz:
job-store-type: jdbc
properties:
org:
quartz:
scheduler:
instanceId: AUTO
dataSource:
myDS:
URL: jdbc:mysql://xxxx:3307/do_xx?useUnicode=true
driver: com.mysql.cj.jdbc.Driver
maxConnections: 5
password: xxxxx
user: xxxx
validationQuery: select 1
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
dataSource: myDS
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
useProperties: false
tablePrefix: QRTZ_
misfireThreshold: 60000
clusterCheckinInterval: 20000
isClustered: true
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true