如何重写Spring Batch中的JdbcStepExecutionDao等现有类?
实现自定义JdbcStepExecutionDao并替换默认实例
我们可以通过继承+重写的方式完成需求,具体步骤如下:
1. 自定义JdbcStepExecutionDao子类
继承Spring Batch原生的JdbcStepExecutionDao,重写getLastStepExecution方法并使用自定义SQL逻辑。由于父类的GET_LAST_STEP_EXECUTION是私有常量无法直接修改,我们直接在子类中定义自己的查询语句即可。
import org.springframework.batch.core.JobInstance; import org.springframework.batch.core.StepExecution; import org.springframework.batch.core.repository.dao.JdbcStepExecutionDao; import org.springframework.jdbc.core.RowMapper; import javax.sql.DataSource; public class CustomJdbcStepExecutionDao extends JdbcStepExecutionDao { // 自定义查询SQL,替换原有逻辑 private static final String CUSTOM_GET_LAST_STEP_EXECUTION = """ SELECT STEP_EXECUTION_ID, VERSION, STEP_NAME, JOB_EXECUTION_ID, START_TIME, END_TIME, STATUS, COMMIT_COUNT, READ_COUNT, FILTER_COUNT, WRITE_COUNT, EXIT_CODE, EXIT_MESSAGE, READ_SKIP_COUNT, WRITE_SKIP_COUNT, PROCESS_SKIP_COUNT, ROLLBACK_COUNT, LAST_UPDATED FROM BATCH_STEP_EXECUTION WHERE JOB_EXECUTION_ID IN ( SELECT JOB_EXECUTION_ID FROM BATCH_JOB_EXECUTION WHERE JOB_INSTANCE_ID = ? ) AND STEP_NAME = ? ORDER BY START_TIME DESC, STEP_EXECUTION_ID DESC LIMIT 1 """; // 必须实现带DataSource的构造方法,继承父类数据源初始化逻辑 public CustomJdbcStepExecutionDao(DataSource dataSource) { super(dataSource); } @Override public StepExecution getLastStepExecution(JobInstance jobInstance, String stepName) { // 使用自定义SQL执行查询,复用父类的结果映射器 return getJdbcTemplate().queryForObject( CUSTOM_GET_LAST_STEP_EXECUTION, new Object[]{jobInstance.getId(), stepName}, createStepExecutionRowMapper() ); } // 可选:如果需要自定义结果映射,重写该方法 // @Override // protected RowMapper<StepExecution> createStepExecutionRowMapper() { // return new CustomStepExecutionRowMapper(); // } }
2. 自定义JobRepositoryFactoryBean子类
继承原生JobRepositoryFactoryBean,重写createStepExecutionDao方法,返回我们自定义的Dao实例,同时传递父类的配置属性(如表前缀、Clob类型),确保与原有配置一致。
import org.springframework.batch.core.repository.dao.StepExecutionDao; import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; import javax.sql.DataSource; public class CustomJobRepositoryFactoryBean extends JobRepositoryFactoryBean { @Override protected StepExecutionDao createStepExecutionDao() throws Exception { DataSource dataSource = getDataSource(); CustomJdbcStepExecutionDao stepExecutionDao = new CustomJdbcStepExecutionDao(dataSource); // 传递父类配置的表前缀、Clob类型等属性 stepExecutionDao.setTablePrefix(getTablePrefix()); stepExecutionDao.setClobType(getClobType()); return stepExecutionDao; } }
3. 配置Spring容器使用自定义FactoryBean
将原生的JobRepositoryFactoryBean替换为我们自定义的实现,确保Spring Batch使用新的Dao实例。
方式1:Java配置类
import org.springframework.batch.core.repository.JobRepository; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; @Configuration public class BatchConfig { @Bean public JobRepository jobRepository(DataSource dataSource) throws Exception { CustomJobRepositoryFactoryBean factory = new CustomJobRepositoryFactoryBean(); factory.setDataSource(dataSource); factory.setTransactionManager(transactionManager(dataSource)); factory.setTablePrefix("BATCH_"); // 保持与原有表前缀一致 factory.afterPropertiesSet(); return factory.getObject(); } @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }
方式2:XML配置
<bean id="jobRepository" class="com.yourpackage.CustomJobRepositoryFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="transactionManager" ref="transactionManager"/> <property name="tablePrefix" value="BATCH_"/> </bean>
关键注意事项
- 自定义SQL必须与数据库表结构完全匹配,避免字段缺失或语法错误;
- 务必传递父类的配置属性(如表前缀),否则会导致Dao无法找到对应的数据表;
- 如果自定义SQL可能返回空结果,可将
queryForObject改为query后判断集合是否为空,避免抛出EmptyResultDataAccessException。
内容的提问来源于stack exchange,提问作者WantBecomeJavaCoder
相关产品推荐
相关产品推荐

