【问题标题】:StoredProcedureItemReader not able to Retry on deadlock exceptionsStoredProcedureItemReader 无法重试死锁异常
【发布时间】:2021-04-19 23:35:30
【问题描述】:

一旦由于数据库上的死锁异常而失败,我很难让我的 StoredProcedureItemReader 重试。
这是我的步骤过程的配置:

@Bean    
public Step Step() throws Exception {       
            return stepBuilderFactory.get("Step")
                    .<Student, Student>chunk(100)
                    .reader(storedProcItemReader())
                    .processor(studentItemProcessor)
                    .writer(fileItemWriter())
                    .faultTolerant()
                    .retryLimit(5)
                    .retry(myException.class)
                    .backOffPolicy(backoffPolicy())
                    .build();
    }

    @Bean
    @StepScope
    public StoredProcedureItemReader<Student> storedProcItemReader() throws Exception {
        return studentItemReader.getDataFromDatabase(dataSource);
    }

studentItemReader 类文件:

@Component
@StepScope
public class studentItemReader{

    @Retryable(include = {DataAccessException.class, JDBCException.class, TransactionException.class, DeadlockLoserDataAccessException.class, Exception.class }, maxAttempts = 5, backoff = @Backoff(delay = 1000,
            maxDelay = 15000, multiplier = 2))
    public StoredProcedureItemReader<Student> getDataFromDatabase(DataSource dataSource) {
        
            StoredProcedureItemReader<RegionResponse> reader = new StoredProcedureItemReader<>();
            
            SqlParameter[] parameter = { new SqlParameter("@studentId",
                    java.sql.Types.INTEGER) };
            PreparedStatementSetter statementValues = new PreparedStatementSetter() {
                @Override
                public void setValues(PreparedStatement ps) throws SQLException {
                    ps.setInt(1, parameterValue);
                    }
            };
            reader.setDataSource(dataSource);
            reader.setProcedureName("dbo.StudentReport");
            reader.setParameters(parameter);
            reader.setPreparedStatementSetter(statementValues);
            reader.setRowMapper(new StudentRowMapper());
            return reader;
        }   
    }
}

所以,问题是在我的 StoredProcedureItemReader 上添加 Retry 后,我无法让 Retry 片段工作。请让我在这里做错了什么。提前致谢!

【问题讨论】:

    标签: spring spring-batch batch-processing


    【解决方案1】:

    您在返回项目阅读器的方法上添加@Retryable。此方法仅在配置时调用。如果您想在抛出异常时在运行时重试读取操作,您应该在阅读器的read 方法上添加注释。添加重试功能的基于注释的方法可能很棘手,这就是为什么我建议使用编程方式来查看实际重试发生的位置。这是一个简单的例子:

    import org.springframework.batch.item.ExecutionContext;
    import org.springframework.batch.item.ItemStreamException;
    import org.springframework.batch.item.ItemStreamReader;
    import org.springframework.batch.item.database.StoredProcedureItemReader;
    import org.springframework.retry.support.RetryTemplate;
    
    public class RetryableItemReader<T> implements ItemStreamReader<T> {
    
        private final StoredProcedureItemReader<T> delegate;
        private final RetryTemplate retryTemplate;
    
        public RetryableItemReader(StoredProcedureItemReader<T> delegate, RetryTemplate retryTemplate) {
            this.delegate = delegate;
            this.retryTemplate = retryTemplate;
        }
    
        @Override
        public T read() throws Exception {
            return retryTemplate.execute(context -> delegate.read());
        }
    
        @Override
        public void open(ExecutionContext executionContext) throws ItemStreamException {
            delegate.open(executionContext);
        }
    
        @Override
        public void update(ExecutionContext executionContext) throws ItemStreamException {
            delegate.update(executionContext);
        }
    
        @Override
        public void close() throws ItemStreamException {
            delegate.close();
        }
    }
    

    然后你可以在你的步骤中使用它作为一个项目阅读器:

    @Bean
    @StepScope
    public RetryableItemReader<Student> storedProcItemReader() {
        RetryTemplate retryTemplate = new RetryTemplateBuilder()
                // define your retry policy
                .build();
        StoredProcedureItemReader<Student> delegateItemReader = new StoredProcedureItemReaderBuilder<Student>()
                // define your delegate item reader
                .build();
        return new RetryableItemReader<>(delegateItemReader, retryTemplate);
    }
    

    【讨论】:

    • 我已经添加了代码。现在我在RetryableItemReader&lt;T&gt; 课堂上得到Caused by: org.springframework.batch.item.ReaderNotOpenException: Reader must be open before it can be read.。你能告诉我如何解决这个问题
    • 我明白了,这是因为我最初回答中的读者实现了ItemReader 而不是ItemStreamReader。我相应地更新了答案。
    • 这里缺少什么来接受答案?我相信示例的更新答案可以回答您的问题,所以请接受它:stackoverflow.com/help/someone-answers。否则让我知道缺少什么。谢谢。
    • 糟糕,抱歉。我以为我已经接受了一段时间。
    猜你喜欢
    • 1970-01-01
    • 2012-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 2011-04-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多