Spring批处理作业实例已存在

时间:2014-10-02 18:16:27

标签: spring spring-batch

行,

我知道以前曾经问过,但我仍然无法找到问题的明确答案。我的问题是:我使用spring批处理将数据导出到SOLR搜索服务器。它需要每分钟运行一次,因此我可以导出所有更新。第一次执行通过OK,但第二次执行抱怨:

2014-10-02 20:37:00,022 [defaultTaskScheduler-1] ERROR: catching
org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException: A job     instance already exists and is complete for parameters={catalogVersionPK=3378876823725152,
type=UPDATE}.  If you want to run this job again, change the parameters.
    at org.springframework.batch.core.repository.support.SimpleJobRepository.createJobExecution(SimpleJobRepository.java:126)
    at 

当然,我可以像这样在作业中添加日期时间参数:

.addLong("time", System.getCurrentTimeMillis())

然后该作业可以多次运行。但是,我也想查询作业的最后一次执行,所以我有这样的代码:

DateTime endTime = new DateTime(0);
JobExecution je = jobRepository.getLastJobExecution("searchExportJob", new JobParametersBuilder().addLong("catalogVersionPK", catalogVersionPK).addString("type", type).toJobParameters());
if (je != null && je.getEndTime() != null) {
   endTime = new DateTime(je.getEndTime());
}

并且没有返回任何内容,因为我没有提供时间参数。所以看起来我可以运行一次并获得最后一次执行时间,或者我可以多次运行它而不是上次执行时间。我真的被卡住了:(

3 个答案:

答案 0 :(得分:4)

按照Luca Basso Ricci的建议使用Job Explorer。

因为您不知道您需要通过实例查找的作业参数。

  1. 查找名为searchExportJob
  2. 的作业的最后一个实例
  3. 查找上面实例的最后一次执行
  4. 这种方式只能使用Spring Batch API

    //We can set count 1 because job instance are ordered by instance id descending
    //so we know the first one returned is the last instance 
    List<JobInstance> instances = jobExplorer.getJobInstances("searchExportJob",0,1);
    JobInstance lastInstance = instances.get(0);
    List<JobExecution> jobExecutions = jobExplorer.getJobExecutions(lastInstance);
    
    //JobExcectuin is ordered by execution id descending so first 
    //result is the last execution
    JobExecution  je = jobExecutions.get(0);
    if (je != null && je.getEndTime() != null) {
         endTime = new DateTime(je.getEndTime());
     }
    

    请注意,此代码仅适用于2.1.x中的Spring Batch 2.2.x及更高版本,API有些不同

答案 1 :(得分:2)

<强>假设

Spring Batch使用一些表来存储使用其参数执行的每个JOB。 如果使用相同参数运行两次作业,则第二个失败,因为作业由jobName和参数标识。

1#解决方案

您可以在运行新作业时使用JobExecution。

JobExecution execution = jobLauncher.run(job, new JobParameters());
.....
// Use a JobExecutionDao to retrieve the JobExecution by ID
JobExecution ex = jobExecutionDao.getJobExecution(execution.getId());

2#解决方案

您可以实现自定义JobExecutionDao并执行自定义查询以在JobExecution表上查找BATCH_JOB_EXECUTIONSee here春天的参考。

我希望我的回答对你有所帮助。

答案 2 :(得分:2)

您可以使用另一个界面:JobExplorer
来自它的javadoc:

  

浏览正在运行或历史作业的执行的入口点   脚步。由于数据可以从持久存储中重新水合,因此   可能不包含当时存在的易失性字段   执行活跃