Как дать разные Бобы в разных классах, используя пакет загрузки весны - PullRequest
0 голосов
/ 25 января 2020

Я пытаюсь загрузить данные с сервера SQL, применить некоторые преобразования и поместить их в CSV с помощью планировщика пружинного пакета. Все отлично работает, когда все в одном классе.

Это мой код:

package com.abc.tools.bootbatch;

@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
@Autowired
public JobBuilderFactory jobBuilderFactory;

@Autowired
public StepBuilderFactory stepBuilderFactory;

@Autowired
public DataSource dataSource;

private static final String qry = "select top 20 colA, colB, colC from ABC";
private Resource outputResource = new FileSystemResource("output/outputData.csv");

@Bean
public DataSource dataSource() {
    final DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(driver_class);
    dataSource.setUrl("db_url");
    dataSource.setUsername(usr);
    dataSource.setPassword(pwd);

    return dataSource;
}

@Bean
ItemReader<Trade> reader() {
    JdbcCursorItemReader<Trade> databaseReader = new JdbcCursorItemReader<>();

    databaseReader.setDataSource(dataSource);
    databaseReader.setSql(qry);
    databaseReader.setRowMapper(new BeanPropertyRowMapper<>(Trade.class));

    return databaseReader;
}

@Bean
public TradeProcessor processor() {
    return new TradeProcessor();
}

@Bean
public FlatFileItemWriter<Trade> writer()
{
    //Create writer instance
    FlatFileItemWriter<Trade> writer = new FlatFileItemWriter<>();

    //Set output file location
    writer.setResource(outputResource);

    //All job repetitions should "append" to same output file
    writer.setAppendAllowed(true);

    //Name field values sequence based on object properties
    writer.setLineAggregator(new DelimitedLineAggregator<Trade>() {
        {
            setDelimiter(",");
            setFieldExtractor(new BeanWrapperFieldExtractor<Trade>() {
                {
                    setNames(new String[] { "colA", "colB", "colC" });
                }
            });
        }
    });
    return writer;
}

@Bean
public Step step1() {
    return stepBuilderFactory.get("step1").<Trade, Trade> chunk(10)
            .reader(reader())
            .processor(processor())
            .writer(writer())
            .build();
}

@Bean
public Job exportUserJob() {
    return jobBuilderFactory.get("exportUserJob")
            .incrementer(new RunIdIncrementer())
            .flow(step1())
            .end()
            .build();
}

}

Когда я разделяю обработку, загрузку и чтение данных в разных классах, он отлично работает с помощью AutoWire , если я не использую пакетную работу. При использовании пакетного задания выдает ошибку при создании экземпляра базы данных. Поэтому я удалил autowire и попытался сделать что-то вроде этого:

@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
@Autowired
public JobBuilderFactory jobBuilderFactory;

@Autowired
public StepBuilderFactory stepBuilderFactory;

@Autowired
public DBConfig dbConfig;

public DataConnection dataconnection=new DataConnection();
DataReader reader=new DataReader();
TradeProcessor processor=new TradeProcessor();
FlatFileWriter flatFileWriter=new FlatFileWriter();

DataSource ds=dataconnection.getDataSource(dbConfig);


@Bean
public Step step1() {
    return stepBuilderFactory.get("step1").<Trade, Trade> chunk(10)
            .reader(reader.reader(ds))
            .processor(processor.processor())
            .writer(flatFileWriter.writer())
            .build();
}

@Bean
public Job exportUserJob() {
    return jobBuilderFactory.get("exportUserJob")
            .incrementer(new RunIdIncrementer())
            .flow(step1())
            .end()
            .build();
}

}

Это дает сбой при инициализации BatchConfiguration

org.springframework.beans.factory.BeanCreationException: ошибка создания компонента с именем 'batchConfiguration'

Я думаю, что мне чего-то не хватает, чтобы все это объединить. Я новичок в весне, любая помощь приветствуется

1 Ответ

0 голосов
/ 27 января 2020

В первом примере вы автоматически подключаете источник данных и объявляете bean-компонент источника данных в том же классе, что неверно. Во втором примере вместо автоматического подключения DBConfig вы можете импортировать его с помощью @Import(DBConfig.class) и автоматически подключать источник данных в своей конфигурации задания по мере необходимости. Вот типичная конфигурация:

@Configuration
public class DBConfig {

   @Bean
   public DataSource dataSource() {
      final DriverManagerDataSource dataSource = new DriverManagerDataSource();
      dataSource.setDriverClassName(driver_class);
      dataSource.setUrl("db_url");
      dataSource.setUsername(usr);
      dataSource.setPassword(pwd);
      return dataSource;
    }

}

@Configuration
@EnableBatchProcessing
@Import(DBConfig.class)
public class BatchConfiguration {

   @Bean
   ItemReader<Trade> reader(DataSource datasource) {
      // use datasource to configure the reader
   }

}

Поскольку вы используете Spring Boot, вы можете удалить класс DBConfig, настроить необходимый источник данных в файле application.properties, и источник данных будет автоматически добавлен в ваш файл. BatchConfiguration.

...