按spring的文档写了个最简单的quatz应用,竟然一直报错说:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.scheduling.quartz.SchedulerFactoryBean' defined in class path resource [applicationContext-rules.xml]: Invocation of init method failed; nested exception is org.quartz.SchedulerConfigException: Failure occured during job recovery. [See nested exception: org.quartz.impl.jdbcjobstore.LockException: Failure obtaining db row lock: Table 'cs.qrtz_locks' doesn't exist [See nested exception: java.sql.SQLException: Table 'cs.qrtz_locks' doesn't exist]]
查论坛得到如下信息:
dwangel 写道
另外可能是自动装配惹得祸,存在dataSource这个bean就自动用数据库的状态维持了。
dwangel 写道
foxty 写道
因为这个时候你的quartz是jobstore用的HDBCJobStore模式,此时会从数据库查询任务。
你如果只是测试的话,可以在你的classpath下加一个文件quartz.properties,并且加上一句org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore 。就会采取内存存储的模式了。
或者可以直接在spring配置中做:
<bean name="quartzScheduler"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="simpleTrigger" />
</list>
</property>
<property name="quartzProperties">
<props>
<prop key="org.quartz.jobStore.class">
org.quartz.simpl.RAMJobStore
</prop>
</props>
</property>
</bean>
autowire真是一个万恶的家伙,出了错让你完全不知道怎么回事. 这个问题整了我一个下午,怒了.
设置org.quartz.jobStore.class为org.quartz.simpl.RAMJobStore也是没有用的.
因为
if (this.dataSource != null) {
mergedProps.put(StdSchedulerFactory.PROP_JOB_STORE_CLASS, LocalDataSourceJobStore.class.getName());
}
SchedulerFactoryBean的setDataSource(DataSource)方法javadoc说:
Set the default DataSource to be used by the Scheduler. If set, this will override corresponding settings in Quartz properties.
Note: If this is set, the Quartz settings should not define a job store "dataSource" to avoid meaningless double configuration.
A Spring-specific subclass of Quartz' JobStoreCMT will be used. It is therefore strongly recommended to perform all operations on the Scheduler within Spring-managed (or plain JTA) transactions. Else, database locking will not properly work and might even break (e.g. if trying to obtain a lock on Oracle without a transaction).
Supports both transactional and non-transactional DataSource access. With a non-XA DataSource and local Spring transactions, a single DataSource argument is sufficient. In case of an XA DataSource and global JTA transactions, SchedulerFactoryBean's "nonTransactionalDataSource" property should be set, passing in a non-XA DataSource that will not participate in global transactions.
See Also:
setNonTransactionalDataSource
setQuartzProperties
setTransactionManager
LocalDataSourceJobStore