首页 > 解决方案 > StoredProcedureItemReader 多线程异常

问题描述

我正在使用 Spring Batch StoredProcedureItemReader 检索结果集并将其插入到另一个使用 JpaItemWriter 的数据库中。下面是我的代码配置。

@Bean
    public JdbcCursorItemReader jdbcCursorItemReader(){
        JdbcCursorItemReader jdbcCursorItemReader = new JdbcCursorItemReader();
        jdbcCursorItemReader.setSql("call myProcedure");
        jdbcCursorItemReader.setRowMapper(new MyRowMapper());
        jdbcCursorItemReader.setDataSource(myDataSource);
        jdbcCursorItemReader.setFetchSize(50);
        jdbcCursorItemReader.setVerifyCursorPosition(false);
        jdbcCursorItemReader.setSaveState(false);
        return jdbcCursorItemReader;
    }


    @Bean
    public Step step() {
        threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(50);
        threadPoolTaskExecutor.setMaxPoolSize(100);
        threadPoolTaskExecutor.setThreadNamePrefix("My-TaskExecutor ");
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(Boolean.TRUE);
        threadPoolTaskExecutor.initialize();
        return stepBuilderFactory.get("myJob").transactionManager(secondaryTransactionManager)
                .chunk(50).reader(jdbcCursorItemReader())
                .writer(myJpaItemWriter())
                .taskExecutor(threadPoolTaskExecutor)
                .throttleLimit(100)
                .build();
    }

该代码在没有多线程或 threadpooltaskexecutor 的情况下工作正常。但是,在使用它们时我遇到以下错误。

Caused by: java.sql.SQLDataException: Current position is after the last row
could not execute statement [n/a] com.microsoft.sqlserver.jdbc.SQLServerException: Violation of PRIMARY KEY constraint

我试过使用 JdbcCursotItemReader,即使那样我也面临同样的错误。关于如何使这项工作的任何建议

标签: multithreadingspring-batch

解决方案


JdbcCursorItemReader不是线程安全的,因为它基于一个ResultSet不是线程安全的。StoredProcedureItemReader也基于 a ,因此ResultSet它也不是线程安全的。见https://stackoverflow.com/a/53964556/5019386

尝试使用JdbcPagingItemReaderwhich是线程安全的,或者如果您真的必须使用StoredProcedureItemReader,则通过将其包装在SynchronizedItemStreamReader.

希望这可以帮助。


推荐阅读