StoredProcedureItemReader 无法重试死锁异常
StoredProcedureItemReader not able to Retry on deadlock exceptions
我很难让我的 StoredProcedureItemReader 在由于数据库上的 deadock 异常而失败后重试。
这是我的步骤过程的配置:
@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 class 文件:
@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 上工作。请告诉我我在这里犯了什么错误。提前致谢!
您正在 @Retryable
添加 returns 项目 reader 的方法。此方法仅在配置时调用。如果您想在每次抛出异常时在运行时重试读取操作,您应该在 reader 的 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();
}
}
然后您可以在您的步骤中将其用作项目reader:
@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);
}
我很难让我的 StoredProcedureItemReader 在由于数据库上的 deadock 异常而失败后重试。
这是我的步骤过程的配置:
@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 class 文件:
@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 上工作。请告诉我我在这里犯了什么错误。提前致谢!
您正在 @Retryable
添加 returns 项目 reader 的方法。此方法仅在配置时调用。如果您想在每次抛出异常时在运行时重试读取操作,您应该在 reader 的 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();
}
}
然后您可以在您的步骤中将其用作项目reader:
@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);
}