Spring批处理作业示例已存在

93ze6v8z  于 2022-12-10  发布在  Spring
关注(0)|答案(5)|浏览(170)

好的,
我知道以前有人问过这个问题,但我还是找不到一个明确的答案。我的问题是:我正在使用spring batch将数据导出到SOLR搜索服务器。它需要每分钟运行一次,所以我可以导出所有的更新。第一次执行通过了,但第二次执行会抱怨:

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());
}

而这个函数什么也不返回,因为我没有提供时间参数。所以看起来我可以运行作业一次并获得最后执行时间,或者我可以运行它多次但不获得最后执行时间。我真的卡住了:(

esyap4oy

esyap4oy1#

假设

Spring Batch使用一些表来存储每个带参数执行的作业。如果您使用相同的参数运行两次作业,第二次会失败,因为作业是由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,并执行一个自定义的查询来在BATCH_JOB_EXECUTION表中查找您的JobExecutionSee here是Spring的引用。
我希望我的回答对你有帮助。

ekqde3dh

ekqde3dh2#

按照Luca Basso Ricci的建议使用作业浏览器。
因为您不知道作业参数,所以需要按示例查找。
1.查找名为searchExportJob的作业的最后一个示例
1.查找上述示例的最后一次执行
这样,您只能使用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());
 }

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

nx7onnlm

nx7onnlm3#

您可以使用另一个界面:JobExplorer
从其javadoc中:
用于浏览正在运行或历史记录的作业和步骤的执行的入口点。由于数据可以从持久性存储中恢复水化,因此它可能不包含在执行处于活动状态时存在的可变字段

nkkqxpd9

nkkqxpd94#

如果您正在调试批处理作业,并在完成之前终止了批处理作业,则在尝试再次启动它时将给予此错误。
要再次启动它,您需要更新作业的名称,以便它创建另一个执行ID。
也可以更新下表。

**批作业执行

批次步骤执行**
需要使用非空值更新StatusEnd_time列。

643ylb08

643ylb085#

每次都创建新的作业运行ID。
如果您的代码涉及使用Jobfactory创建Job对象,则下面的代码片段将有助于解决该问题:

return jobBuilderFactory
    .get("someJobName")
    .incrementer(new RunIdIncrementer())   // solution lies here- creating new job id everytime
    .flow(                                 // and here
        stepBuilderFactory
            .get("someTaskletStepName")
            .tasklet(tasklet)   // u can replace it with step
            .allowStartIfComplete(true)    // this will make the job run even if complete in last run 
            .build())
    .end()
    .build();

相关问题