Spring batch JdbcPagingItemReader не может прочитать все события - PullRequest
0 голосов
/ 04 января 2019

У меня было приложение Spring Batch, как показано ниже (имя таблицы и запрос редактируются для некоторых общих имен)

когда я запустил эту программу, она смогла прочитать 7500 событий, то есть в 3 раза больше размера куска, и не смогла прочитать оставшиеся записи в базе данных оракула. У меня была таблица, содержащая 50 миллионов записей, и я мог скопировать ее в другую базу данных noSql.

@EnableBatchProcessing
@SpringBootApplication
@EnableAutoConfiguration
public class MultiThreadPagingApp extends DefaultBatchConfigurer{

@Autowired
private JobBuilderFactory jobBuilderFactory;

@Autowired
private StepBuilderFactory stepBuilderFactory;

@Autowired
public DataSource dataSource;

@Bean
public DataSource dataSource() {
    final DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName("oracle.jdbc.OracleDriver");
    dataSource.setUrl("jdbc:oracle:thin:@***********");
    dataSource.setUsername("user");
    dataSource.setPassword("password");

    return dataSource;
}


@Override
public void setDataSource(DataSource dataSource) {}

@Bean
@StepScope
ItemReader<UserModel> dbReader() throws Exception {

    JdbcPagingItemReader<UserModel> reader = new JdbcPagingItemReader<UserModel>();
    final SqlPagingQueryProviderFactoryBean sqlPagingQueryProviderFactoryBean = new SqlPagingQueryProviderFactoryBean();        
    sqlPagingQueryProviderFactoryBean.setDataSource(dataSource);
    sqlPagingQueryProviderFactoryBean.setSelectClause("select * ");
    sqlPagingQueryProviderFactoryBean.setFromClause("from user");
    sqlPagingQueryProviderFactoryBean.setWhereClause("where id>0");
    sqlPagingQueryProviderFactoryBean.setSortKey("name");
    reader.setQueryProvider(sqlPagingQueryProviderFactoryBean.getObject());
    reader.setDataSource(dataSource);
    reader.setPageSize(2500);       
    reader.setRowMapper(new BeanPropertyRowMapper<>(UserModel.class));
    reader.afterPropertiesSet();
    reader.setSaveState(true);
    System.out.println("Reading users anonymized in chunks of {}"+ 2500);
    return reader;
}


@Bean
public Dbwriter writer() {
    return new Dbwriter(); // I had another class for this
}   

@Bean
public Step step1() throws Exception {
    ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
    taskExecutor.setCorePoolSize(4);
    taskExecutor.setMaxPoolSize(10);
    taskExecutor.afterPropertiesSet();

    return this.stepBuilderFactory.get("step1")
            .<UserModel, UserModel>chunk(2500)
            .reader(dbReader())
            .writer(writer())
            .taskExecutor(taskExecutor)
            .build();
}


@Bean
public Job multithreadedJob() throws Exception {
    return this.jobBuilderFactory.get("multithreadedJob")
            .start(step1())
            .build();
} 


@Bean
public PlatformTransactionManager getTransactionManager() {
    return new ResourcelessTransactionManager();
}

@Bean
public JobRepository getJobRepo() throws Exception {
    return new MapJobRepositoryFactoryBean(getTransactionManager()).getObject();
}

public static void main(String[] args) {
    SpringApplication.run(MultiThreadPagingApp.class, args);
}

}

Можете ли вы помочь мне, как я могу эффективно прочитать все записи, используя Spring Batch, или помочь мне с любым другим подходом к этому. Я попробовал один подход, упомянутый здесь: http://techdive.in/java/jdbc-handling-huge-resultset Потребовалось 120 минут, чтобы прочитать и сохранить все записи с помощью однопоточного приложения. Поскольку для этого лучше всего подходит пружинная партия, я предполагаю, что мы справимся с этим сценарием в кратчайшие сроки.

1 Ответ

0 голосов
/ 06 января 2019

Вы устанавливаете флаг saveState в значение true (кстати, его следует установить перед вызовом afterPropertiesSet) на JdbcPagingItemReader и использовать этот ридер в многопоточном шаге. Однако задокументировано для установки этого флага в false в многопоточном контексте.

Многопоточность с читателями баз данных обычно не лучший вариант, я бы рекомендовал использовать разбиение в вашем случае.

...