Spring Batch

时间:2018-05-06 10:25:31

标签: spring spring-boot spring-batch

您好我最近一直在Spring批处理,需要一些帮助。

1)我想使用多个线程运行我的Job,因此我使用了TaskExecutor,如下所示,

            @Bean
            public TaskExecutor taskExecutor() {
                SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
                taskExecutor.setConcurrencyLimit(4);
                return taskExecutor;
            }

    @Bean
        public Step myStep() {
            return stepBuilderFactory.get("myStep")
                    .<MyEntity,AnotherEntity> chunk(1)
                    .reader(reader())
                    .processor(processor())
                    .writer(writer())
                    .taskExecutor(taskExecutor())
                    .throttleLimit(4)
                     .build();
        }

但是,执行时可以在控制台中查看以下行。

  

o.s.b.c.l.support.SimpleJobLauncher:没有设置TaskExecutor,默认为同步执行程序。

这是什么意思?但是,在调试时我可以看到四个SimpleAsyncExecutor线程正在运行。有人可以对此有所了解吗?

2)我不想使用Spring批量创建的元数据表运行我的批处理应用程序。我尝试添加spring.batch.initialize-schema=never。但它没有用。我还使用ResourcelessTransactionManagerMapJobRepositoryFactoryBean看到了一些方法。但是我必须为我的工作做一些数据库事务。如果我使用它会好吗? 我也可以通过扩展DefaultBatchConfigurer和覆盖:

来实现这一目标
@Override
    public void setDataSource(DataSource dataSource) {
        // override to do not set datasource even if a datasource exist.
        // initialize will use a Map based JobRepository (instead of database)
    }

请进一步指导我。感谢。

更新

我的完整配置类。

@EnableBatchProcessing
@EnableScheduling
@Configuration
public class MyBatchConfiguration{

    @Autowired
    public JobBuilderFactory jobBuilderFactory;

    @Autowired
    public StepBuilderFactory stepBuilderFactory;

    @Autowired
    public DataSource dataSource;


    /* @Override
        public void setDataSource(DataSource dataSource) {
            // override to do not set datasource even if a datasource exist.
            // initialize will use a Map based JobRepository (instead of database)
        }*/
    @Bean
    public Step myStep() {

        return stepBuilderFactory.get("myStep")
                .<MyEntity,AnotherEntity> chunk(1)
                .reader(reader())
                .processor(processor())
                .writer(writer())
                .taskExecutor(executor())
                .throttleLimit(4)
                .build();
    }

    @Bean
    public Job myJob() {

        return jobBuilderFactory.get("myJob")
                .incrementer(new RunIdIncrementer())
                .listener(listener())
                .flow(myStep())
                .end()
                .build();
    }

    @Bean
    public MyJobListener myJobListener()
    {
        return new MyJobListener();
    }
    @Bean
    public ItemReader<MyEntity> reader()
    {

        return new MyReader();
    }

    @Bean
    public ItemWriter<? super AnotherEntity> writer()
    {
        return new MyWriter();
    }

    @Bean
    public ItemProcessor<MyEntity,AnotherEntity> processor()
    {
        return new MyProcessor();
    }

    @Bean
    public TaskExecutor taskExecutor() {
        SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
        taskExecutor.setConcurrencyLimit(4);
        return taskExecutor;
    }}

1 个答案:

答案 0 :(得分:1)

将来,请将其分解为两个独立的问题。话虽如此,让我对这两个问题有所了解。

SimpleJobLauncher:没有设置TaskExecutor,默认为同步执行程序。

您的配置正在配置myStep以使用您的TaskExecutor。这样做是因为它导致Spring Batch在其自己的线程中执行每个块(基于TaskExecutor的参数)。您看到的日志消息与该行为无关。它与启动你的工作有关。默认情况下,SimpleJobLauncher将在其运行的同一线程上启动作业,从而阻止该线程。您可以TaskExecutor注入SimpleJobLauncher,这将导致作业在与JobLauncher本身不同的线程上执行。这些是框架对多个线程的两个单独使用。

我不想使用春季批量创建的元数据表运行我的批处理应用程序

这里简短的回答是只使用内存数据库(如HSQLDB或H2)作为元数据表。这提供了生产级数据存储(以便正确处理并发),而不实际持久化数据。如果您使用ResourcelessTransactionManager,则实际上是关闭了交易(如果您以任何身份使用数据库,这是一个糟糕的主意),因为TransactionManager实际上并没有做任何事情(它和&#1}} #39; sa no-op implementation。)