You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何重写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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 07:05:29