我如何在 Quartz 中使用 SQLite?
How can I use SQLite in Quartz?
我正在尝试在应用程序中将 quartz 与 SQLite 结合使用。当我阅读文档 here 时,我注意到他们没有在可用的数据库中提及 SQLite。他们说:
JDBCJobStore works with nearly any database, it has been used widely
with Oracle, PostgreSQL, MySQL, MS SQLServer, HSQLDB, and DB2. To use
JDBCJobStore, you must first create a set of database tables for
Quartz to use. You can find table-creation SQL scripts in the
“docs/dbTables” directory of the Quartz distribution.
因此,根据这个问题:Which setup script to use for setting up quartz sqlite table? 我使用 derby 脚本作为我的 sqlite 脚本。
问题是当我试图在之前插入的作业中安排触发器时。这是我的代码的一部分:
// and start it off
scheduler.start();
Map<String, String> map = new HashMap<>();
map.put("key", "value");
JobDataMap jdm = new JobDataMap(map);
JobKey key = new JobKey("job1", "key1");
if(!scheduler.checkExists(key)){
JobDetail job = newJob(HelloJob.class).withIdentity(key).storeDurably().usingJobData(jdm).build();
addJob(scheduler, job);
// Trigger the job to run now, and then repeat every 40 seconds
Trigger trigger = newTrigger()
.withIdentity("trigger1", "group1")
.startNow()
.forJob(job)
.withSchedule(simpleSchedule()
.withIntervalInSeconds(40)
.repeatForever())
.build();
// Tell quartz to schedule the job using our trigger
scheduler.scheduleJob(trigger); // here is where I get an error
}
Thread.sleep(60000);
scheduler.shutdown();
我的quartz.properties是这样的:
org.quartz.scheduler.instanceName = MyScheduler
org.quartz.threadPool.threadCount = 5
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.dataSource.SQLiteDB.driver = org.sqlite.JDBC
org.quartz.dataSource.SQLiteDB.URL = jdbc:sqlite:bota.db
org.quartz.dataSource.SQLiteDB.maxConnections = 30
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.dataSource = SQLiteDB
我使用的是 sqlite v-3.8.11.2 和 quartz v-2.2.2。这是我在日志中得到的:
org.quartz.JobPersistenceException: Couldn't store trigger 'group1.trigger1' for 'key1.job1' job:Couldn't retrieve job: not implemented by SQLite JDBC driver [See nested exception: org.quartz.JobPersistenceException: Couldn't retrieve job: not implemented by SQLite JDBC driver [See nested exception: java.sql.SQLException: not implemented by SQLite JDBC driver]]
at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1223)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeVoid(JobStoreSupport.java:1159)
at org.quartz.impl.jdbcjobstore.JobStoreSupport$VoidTransactionCallback.execute(JobStoreSupport.java:3715)
at org.quartz.impl.jdbcjobstore.JobStoreSupport$VoidTransactionCallback.execute(JobStoreSupport.java:3713)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3799)
at org.quartz.impl.jdbcjobstore.JobStoreTX.executeInLock(JobStoreTX.java:93)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1155)
at org.quartz.core.QuartzScheduler.scheduleJob(QuartzScheduler.java:932)
at org.quartz.impl.StdScheduler.scheduleJob(StdScheduler.java:258)
at javaapplication2.JavaApplication2.main(JavaApplication2.java:174)
Caused by: org.quartz.JobPersistenceException: Couldn't retrieve job: not implemented by SQLite JDBC driver [See nested exception: java.sql.SQLException: not implemented by SQLite JDBC driver]
at org.quartz.impl.jdbcjobstore.JobStoreSupport.retrieveJob(JobStoreSupport.java:1396)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1205)
... 9 more
Caused by: java.sql.SQLException: not implemented by SQLite JDBC driver
at org.sqlite.jdbc4.JDBC4ResultSet.unused(JDBC4ResultSet.java:320)
at org.sqlite.jdbc4.JDBC4ResultSet.getBlob(JDBC4ResultSet.java:345)
at com.mchange.v2.c3p0.impl.NewProxyResultSet.getBlob(NewProxyResultSet.java:285)
at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.getObjectFromBlob(StdJDBCDelegate.java:3190)
at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.selectJobDetail(StdJDBCDelegate.java:860)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.retrieveJob(JobStoreSupport.java:1385)
... 10 more
BUILD STOPPED (total time: 11 seconds)
问题似乎是 sqlite jdbc 驱动 does not support the method ResultSet.getBlob().
但是 quartz 使用此方法来检索分配给作业的 JobDataMap。
如果您仍想将 quartz 与 sqlite 一起使用,您可以扩展 StdJDBCDelegate and retrieve/set blobs like suggested in this answer。
乍一看似乎只需要覆盖方法
- StdJDBCDelegate.getObjectFromBlob() 和
- StdJDBCDelegate.getJobDataFromBlob()
因为我不确定以后是否会出现更多问题(例如你可以看到 sqlite jdbc 驱动程序有更多 unsupported ResultSet methods )我宁愿推荐使用一个数据库开箱即用。
根据 mam10eks 的建议,以下代码对我有用。
package com.example.quartz.sqlite;
import org.quartz.impl.jdbcjobstore.StdJDBCDelegate;
import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.sql.ResultSet;
import java.sql.SQLException;
public class CustomJDBCDelegate extends StdJDBCDelegate {
@Override
protected Object getObjectFromBlob(ResultSet rs, String colName) throws ClassNotFoundException, IOException, SQLException {
byte[] bytes = rs.getBytes(colName);
Object map = null;
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try {
bais = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bais);
map = ois.readObject();
} catch (EOFException ex1) {
bais.close();
} catch (IOException e) {
// Error in de-serialization
e.printStackTrace();
}
return map;
}
@Override
protected Object getJobDataFromBlob(ResultSet rs, String colName) throws ClassNotFoundException, IOException, SQLException {
return getObjectFromBlob(rs, colName);
}
}
现在将以下内容放入quartz.properties
org.quartz.jobStore.driverDelegateClass=com.example.quartz.sqlite.CustomJDBCDelegate
我正在尝试在应用程序中将 quartz 与 SQLite 结合使用。当我阅读文档 here 时,我注意到他们没有在可用的数据库中提及 SQLite。他们说:
JDBCJobStore works with nearly any database, it has been used widely with Oracle, PostgreSQL, MySQL, MS SQLServer, HSQLDB, and DB2. To use JDBCJobStore, you must first create a set of database tables for Quartz to use. You can find table-creation SQL scripts in the “docs/dbTables” directory of the Quartz distribution.
因此,根据这个问题:Which setup script to use for setting up quartz sqlite table? 我使用 derby 脚本作为我的 sqlite 脚本。
问题是当我试图在之前插入的作业中安排触发器时。这是我的代码的一部分:
// and start it off
scheduler.start();
Map<String, String> map = new HashMap<>();
map.put("key", "value");
JobDataMap jdm = new JobDataMap(map);
JobKey key = new JobKey("job1", "key1");
if(!scheduler.checkExists(key)){
JobDetail job = newJob(HelloJob.class).withIdentity(key).storeDurably().usingJobData(jdm).build();
addJob(scheduler, job);
// Trigger the job to run now, and then repeat every 40 seconds
Trigger trigger = newTrigger()
.withIdentity("trigger1", "group1")
.startNow()
.forJob(job)
.withSchedule(simpleSchedule()
.withIntervalInSeconds(40)
.repeatForever())
.build();
// Tell quartz to schedule the job using our trigger
scheduler.scheduleJob(trigger); // here is where I get an error
}
Thread.sleep(60000);
scheduler.shutdown();
我的quartz.properties是这样的:
org.quartz.scheduler.instanceName = MyScheduler
org.quartz.threadPool.threadCount = 5
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.dataSource.SQLiteDB.driver = org.sqlite.JDBC
org.quartz.dataSource.SQLiteDB.URL = jdbc:sqlite:bota.db
org.quartz.dataSource.SQLiteDB.maxConnections = 30
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.dataSource = SQLiteDB
我使用的是 sqlite v-3.8.11.2 和 quartz v-2.2.2。这是我在日志中得到的:
org.quartz.JobPersistenceException: Couldn't store trigger 'group1.trigger1' for 'key1.job1' job:Couldn't retrieve job: not implemented by SQLite JDBC driver [See nested exception: org.quartz.JobPersistenceException: Couldn't retrieve job: not implemented by SQLite JDBC driver [See nested exception: java.sql.SQLException: not implemented by SQLite JDBC driver]]
at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1223)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeVoid(JobStoreSupport.java:1159)
at org.quartz.impl.jdbcjobstore.JobStoreSupport$VoidTransactionCallback.execute(JobStoreSupport.java:3715)
at org.quartz.impl.jdbcjobstore.JobStoreSupport$VoidTransactionCallback.execute(JobStoreSupport.java:3713)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3799)
at org.quartz.impl.jdbcjobstore.JobStoreTX.executeInLock(JobStoreTX.java:93)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1155)
at org.quartz.core.QuartzScheduler.scheduleJob(QuartzScheduler.java:932)
at org.quartz.impl.StdScheduler.scheduleJob(StdScheduler.java:258)
at javaapplication2.JavaApplication2.main(JavaApplication2.java:174)
Caused by: org.quartz.JobPersistenceException: Couldn't retrieve job: not implemented by SQLite JDBC driver [See nested exception: java.sql.SQLException: not implemented by SQLite JDBC driver]
at org.quartz.impl.jdbcjobstore.JobStoreSupport.retrieveJob(JobStoreSupport.java:1396)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1205)
... 9 more
Caused by: java.sql.SQLException: not implemented by SQLite JDBC driver
at org.sqlite.jdbc4.JDBC4ResultSet.unused(JDBC4ResultSet.java:320)
at org.sqlite.jdbc4.JDBC4ResultSet.getBlob(JDBC4ResultSet.java:345)
at com.mchange.v2.c3p0.impl.NewProxyResultSet.getBlob(NewProxyResultSet.java:285)
at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.getObjectFromBlob(StdJDBCDelegate.java:3190)
at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.selectJobDetail(StdJDBCDelegate.java:860)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.retrieveJob(JobStoreSupport.java:1385)
... 10 more
BUILD STOPPED (total time: 11 seconds)
问题似乎是 sqlite jdbc 驱动 does not support the method ResultSet.getBlob().
但是 quartz 使用此方法来检索分配给作业的 JobDataMap。
如果您仍想将 quartz 与 sqlite 一起使用,您可以扩展 StdJDBCDelegate and retrieve/set blobs like suggested in this answer。
乍一看似乎只需要覆盖方法
- StdJDBCDelegate.getObjectFromBlob() 和
- StdJDBCDelegate.getJobDataFromBlob()
因为我不确定以后是否会出现更多问题(例如你可以看到 sqlite jdbc 驱动程序有更多 unsupported ResultSet methods )我宁愿推荐使用一个数据库开箱即用。
根据 mam10eks 的建议,以下代码对我有用。
package com.example.quartz.sqlite;
import org.quartz.impl.jdbcjobstore.StdJDBCDelegate;
import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.sql.ResultSet;
import java.sql.SQLException;
public class CustomJDBCDelegate extends StdJDBCDelegate {
@Override
protected Object getObjectFromBlob(ResultSet rs, String colName) throws ClassNotFoundException, IOException, SQLException {
byte[] bytes = rs.getBytes(colName);
Object map = null;
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try {
bais = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bais);
map = ois.readObject();
} catch (EOFException ex1) {
bais.close();
} catch (IOException e) {
// Error in de-serialization
e.printStackTrace();
}
return map;
}
@Override
protected Object getJobDataFromBlob(ResultSet rs, String colName) throws ClassNotFoundException, IOException, SQLException {
return getObjectFromBlob(rs, colName);
}
}
现在将以下内容放入quartz.properties
org.quartz.jobStore.driverDelegateClass=com.example.quartz.sqlite.CustomJDBCDelegate