spring批处理:不能用不同的jobparameters启动作业,也不能访问jobparameters

yzuktlbb  于 2021-07-23  发布在  Java
关注(0)|答案(1)|浏览(346)

我得解决Spring批的问题。两者都与通过命令行传入的jobparameters有关。
第一期:
我正在使用eclipse开发我的应用程序并对其进行测试。因此,我补充道 Program argumentsRun Configurations . 这些论点是:

-ts=${current_date} -path="file.csv"

运行应用程序将引发异常。例外情况是:

Caused by: org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException: 
A job instance already exists and is complete for parameters={ts=20210211_1631, path=file.csv}.  
If you want to run this job again, change the parameters.

正如您所看到的,jobparameters对于每个执行应该是不同的,因为其中一个参数是每分钟都在变化的时间戳。我看过这个问题springbatch:用不同的参数执行同一个作业,但这里的解决方案是为每个作业执行设置一个新名称(例如。 name + System.currentTimeMillis() ). 这个问题还有别的解决办法吗?我不想每次执行作业时都为其创建一个“随机”名称。我的工作如下:

@Bean(name = "inJob")
public Job inJob(JobRepository jobRepository) {
    return jobBuilderFactory.get("inJob")
            .repository(jobRepository)
            .incrementer(new RunIdIncrementer())
            .start(truncateTable())
            .next(loadCsv())
            .next(updateType())
            .build();
}

我正在使用jobrepository的自定义实现将元数据存储在不同的数据库架构中:

@Override
public JobRepository createJobRepository() throws Exception {
    JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
    factory.setDataSource(dataSource);
    factory.setTransactionManager(transactionManager);
    factory.setTablePrefix("logging.BATCH_");
    return factory.getObject();
}

第二期:
我的第二个问题是访问jobparameters。以上参数之一是我要在flatfileitemreader中使用的文件路径:

@Bean(name = "inReader")
@StepScope
public FlatFileItemReader<CsvInfile> inReader() {       
    FlatFileItemReader<CsvInfile> reader = new FlatFileItemReader<CsvInfile>();
    reader.setResource(new FileSystemResource(path));
    DefaultLineMapper<CsvInfile> lineMapper = new DefaultLineMapper<>();
    lineMapper.setFieldSetMapper(new CsvInfileFieldMapper());
    DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
    tokenizer.setDelimiter("|");
    tokenizer.setNames(ccn.names);
    lineMapper.setLineTokenizer(tokenizer);
    reader.setLineMapper(lineMapper);
    reader.setLinesToSkip(1);
    reader.open(new ExecutionContext());
    return reader;
}

为了从jobparameters获取路径,我使用beforstep注解加载jobparameters并将它们复制到局部变量上。不幸的是,这不起作用。变量将是 null 执行失败,因为文件无法打开。

private String path;

@BeforeStep
public void beforeStep(StepExecution stepExecution) {
    JobParameters jobParameters = stepExecution.getJobParameters();
    this.path = jobParameters.getString("path");
}

如何访问读卡器中的jobparameters?我想作为命令行参数传入文件路径,然后读取此文件。

2wnc66cl

2wnc66cl1#

第一个问题:这个问题还有别的解决办法吗?
当前日期是按分钟解析的,因此如果在该分钟内多次运行作业,则可能已经有一个具有相同参数的作业示例,因此会出现问题。你的 ts 参数的精度应为秒(如果需要,可以小于秒)。
第二个问题:如何在我的阅读器中访问jobparameters?我想作为命令行参数传入文件路径,然后读取此文件。
你不需要这个 beforeStep 方法。可以按如下方式在bean定义中延迟绑定job参数:

@Bean(name = "inReader")
@StepScope
public FlatFileItemReader<CsvInfile> inReader(@Value("#{jobParameters['path']}") String path) {       
    FlatFileItemReader<CsvInfile> reader = new FlatFileItemReader<CsvInfile>();
    reader.setResource(new FileSystemResource(path));
    // ...
    return reader;
}

如果您传递 path 作为作业参数,类似于:

java -jar myjob.jar path=/absolute/path/to/your/file

参考文档的作业和步骤属性后期绑定部分对此进行了解释。

相关问题