storedprocedureitemreader无法重试死锁异常

qyuhtwio  于 2021-07-14  发布在  Java
关注(0)|答案(1)|浏览(301)

我很难让我的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;
        }   
    }
}

所以,问题是在添加了retry之后,我无法让retry条目在storedprocedureitemreader上工作。请告诉我我犯了什么错误。提前谢谢!

lyr7nygr

lyr7nygr1#

您正在添加 @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);
}

相关问题