Quartz是怎样将job持久化到数据库的

Quartz在QRTZ_JOB_DETAILS表中存储了什么

因为本文章是说明Quartz在QRTZ_JOB_DETAILS表中存储了什么的,所以本篇文章的前提是quartz的配置中是使用了jdbcjobstore的,并且driver代理这里我们使用的是StdJDBCDelegate。

1.QRTZ_JOB_DETAIL表

Quartz是怎样将job持久化到数据库的

这张表是quartz存储job的表,按字面意思这些字段分别为

SCHED_NAME:计划名字
JOB_NAME:工作名字
JOB_GROUP:工作组
DESCRIPTION:描述
JOB_CLASS_NAME:工作类名字
IS_DURABLE:是否持久化
IS_NONCONCURRENT:是否同步
IS_UPDATE_DATA:是否更新数据
REQUESTS_RECOVERY:是否要求唤醒
JOB_DATA:job数据

现在我们了解了这些字段的名字,但是我们不知到这些字段里面有什么。所以接下来我们要去了解一下quartz在这些字段中存储了什么。

2. StdJDBCDelegate

/**
     * <p>
     * Insert the job detail record.
     * </p>
     * 
     * @param conn
     *          the DB Connection
     * @param job
     *          the job to insert
     * @return number of rows inserted
     * @throws IOException
     *           if there were problems serializing the JobDataMap
     */
    public int insertJobDetail(Connection conn, JobDetail job)
        throws IOException, SQLException {
        ByteArrayOutputStream baos = serializeJobData(job.getJobDataMap());

        PreparedStatement ps = null;

        int insertResult = 0;

        try {
            ps = conn.prepareStatement(rtp(INSERT_JOB_DETAIL));
            ps.setString(1, job.getKey().getName());
            ps.setString(2, job.getKey().getGroup());
            ps.setString(3, job.getDescription());
            ps.setString(4, job.getJobClass().getName());
            setBoolean(ps, 5, job.isDurable());
            setBoolean(ps, 6, job.isConcurrentExectionDisallowed());
            setBoolean(ps, 7, job.isPersistJobDataAfterExecution());
            setBoolean(ps, 8, job.requestsRecovery());
            setBytes(ps, 9, baos);

            insertResult = ps.executeUpdate();
        } finally {
            closeStatement(ps);
        }

        return insertResult;
    }

这是我从quartz的源码StdJDBCDelegate类中发现的,因为我们的driver代理用的就是StdJDBCDelegate,所以往数据库中插入job的应该就是这个方法。
其中我们可以发现,QRTZ_JOB_DETAIL表中的大部分字段都可以在这里找到,除了SCHED_NAME和JOB_DATA字段没有其他都有了,那这两个字段都是存了什么呢?
接下来我们打开插入job的sql语句看看(点击PreparedStatement方法中的参数就可以看到):

String INSERT_JOB_DETAIL = "INSERT INTO "
            + TABLE_PREFIX_SUBST + TABLE_JOB_DETAILS + " (" 
            + COL_SCHEDULER_NAME + ", " + COL_JOB_NAME
            + ", " + COL_JOB_GROUP + ", " + COL_DESCRIPTION + ", "
            + COL_JOB_CLASS + ", " + COL_IS_DURABLE + ", " 
            + COL_IS_NONCONCURRENT +  ", " + COL_IS_UPDATE_DATA + ", " 
            + COL_REQUESTS_RECOVERY + ", "
            + COL_JOB_DATAMAP + ") " + " VALUES(" + SCHED_NAME_SUBST + ", ?, ?, ?, ?, ?, ?, ?, ?, ?)";

这里我们发现SCHED_NAME字段的内容是已经在sql中预设好的与job没有什么关联,所以这里我们不去深究,接下来是JOB_DATA字段里面是什么呢?让我们回到原先的insertJobDetail方法中,在执行语句前有一个setBytes方法,其中有两个参数一个是9,另一个是job的jobDataMap的输出流。QRTZ_JOB_DETAIL表中有10个字段,去掉SCHED_NAME,还剩9个,所以我们可以推断出JOB_DATA字段中存储的就是jobDataMap里面的数据。
其他8个字段中JOB_NAME和JOB_GROUP我就不说了,大家应该可以知道是什么。其他6个字段我们一一点进JobDetai类中看看是什么。

这里我是翻译的英文注释
DESCRIPTION:返回对创建者对job实例的描述(如果有的话)。所以显而易见,这个属性对job没什么大用,他只是类似于对这个job实例的注释而已。
JOB_CLASS_NAME:获得将要执行的job实例(这里的注释讲的不是很明白,但是根据代码我们可以知道,个字段存储的是当前我们实现的job类的包路径)
IS_DURABLE:job完成后(没有trigger指向他)是否要保留数据库记录
IS_NONCONCURRENT:关联的job类是否有DisallowConcurrentExecution注解,被标注的job类不能同时执行多个实例
IS_UPDATE_DATA:关联的job类是否有DisallowConcurrentExecution注解,被标注的job类在执行期间会更新jobDataMap中的数据,并且将更新后的jobDataMap数据重新储存到数据库
REQUESTS_RECOVERY:在当前job尚未执行时,当前quartz节点在宕机重启或者故障转移后是否还要执行该job。

至此说明完毕,仅代表个人观点,如有疑问可以在评论区回复。

上一篇:Quartz(3):simpleTrigger和cronTrigger触发器的介绍


下一篇:FreeMaker模板搭配Quartz的使用