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

Spring Boot Batch查询MySQL时出现BadSqlGrammarException问题求助

Spring Boot Batch查询MySQL时出现BadSqlGrammarException问题求助

大家好,我正在开发一个Spring Boot Batch的示例项目,使用的spring-boot-starter-parent版本是3.4.3.RELEASE。我的需求是当定时任务触发时,从MySQL数据库中拉取昨天22:00到今天22:00这个时间段内插入的Transaction记录,但执行过程中一直抛出下面的SQL语法错误:

org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [SELECT unique_tx_id, created_time FROM Transaction WHERE created_time BETWEEN ? AND ? ORDER BY unique_tx_id ASC LIMIT 10], 

我已经尝试了好几种调整方式,但还是没能解决这个问题,希望大家能给我一些排查思路或者修复建议。

下面是我的相关代码:

BatchConfig类

@Configuration
@EnableBatchProcessing
public class BatchConfig {
    private final DataSource dataSource;
    private final ExcelWriter excelWriter;

    public BatchConfig(DataSource dataSource, ExcelWriter excelWriter) {
        this.dataSource = dataSource;
        this.excelWriter = excelWriter;
    }

    @Bean
    public Job transactionExportJob(
        JobRepository jobRepository, Step exportStep) {
        return new JobBuilder("transactionExportJob", jobRepository)
            .incrementer(new RunIdIncrementer())
            .start(exportStep)
            .build();
    }

    @Bean
    public Step exportStep(JobRepository jobRepository,
        PlatformTransactionManager transactionManager,
        ItemReader<Transaction> reader, ExcelWriter excelWriter) {
        return new StepBuilder("exportStep", jobRepository)
            .<Transaction, Transaction>chunk(5000, transactionManager)
            .reader(reader)
            .processor(new TransactionProcessor())
            .writer(excelWriter)
            .faultTolerant()
            .retryLimit(3)
            .retry(Exception.class)
            .skip(Exception.class)
            .skipLimit(100)
            .listener(new CustomSkipListener())
            .build();
    }

    @Bean
    public JdbcPagingItemReader<Transaction> reader(
        PagingQueryProvider transactionQueryProvider) {
        JdbcPagingItemReader<Transaction> reader = new JdbcPagingItemReader<>();
        reader.setDataSource(dataSource);
        reader.setFetchSize(5000);
        reader.setRowMapper(new TransactionRowMapper());
        reader.setQueryProvider(transactionQueryProvider);
        return reader;
    }
}

BatchScheduler类

@Component
public class BatchScheduler {
    private final JobLauncher jobLauncher;
    private final Job transactionExportJob;

    public BatchScheduler(JobLauncher jobLauncher, Job transactionExportJob) {
        this.jobLauncher = jobLauncher;
        this.transactionExportJob = transactionExportJob;
    }

    @Scheduled(cron = "0 0 22 * * ?", zone = "Asia/Kolkata")
    public void runBatchJob() {
        try {
            LocalDateTime startTime =
                LocalDateTime.now().minusDays(1).withHour(22);
            LocalDateTime endTime = LocalDateTime.now().withHour(22);
            JobParameters jobParameters =
                new JobParametersBuilder()
                    .addDate("startTime",
                        Date.from(startTime.atZone(ZoneId.of("Asia/Kolkata"))
                                      .toInstant()))
                    .addDate("endTime",
                        Date.from(endTime.atZone(ZoneId.of("Asia/Kolkata"))
                                      .toInstant()))
                    .toJobParameters();

            System.out.println("Batch Job started");
            JobExecution execution =
                jobLauncher.run(transactionExportJob, jobParameters);
            System.out.println(
                "Batch job completed with status: {}" + execution.getStatus());

        } catch (Exception e) {
            System.out.println(
                "Batch job execution failed: {}" + e.getMessage() + e);
        }
    }
}

TransactionQueryConfig类

@Configuration
public class TransactionQueryConfig {
    @Bean
    public PagingQueryProvider transactionQueryProvider(DataSource dataSource) {
        SqlPagingQueryProviderFactoryBean provider =
            new SqlPagingQueryProviderFactoryBean();
        provider.setDataSource(dataSource);
        provider.setSelectClause("SELECT unique_tx_id, created_time");
        provider.setFromClause("FROM Transaction");
        provider.setWhereClause("WHERE created_time BETWEEN ? AND ?");
        provider.setSortKey("unique_tx_id");

        try {
            return provider.getObject(); // Convert to PagingQueryProvider
        } catch (Exception e) {
            throw new RuntimeException(
                "Error creating PagingQueryProvider: " + e.getMessage(), e);
        }
    }
}

TransactionRowMapper类

public class TransactionRowMapper implements RowMapper<Transaction> {
    @Override
    public Transaction mapRow(ResultSet rs, int rowNum) throws SQLException {
        return new Transaction(rs.getString("unique_tx_id"),
            rs.getTimestamp("created_time").toLocalDateTime());
    }
}

我期望代码能正常运行,成功从数据库中查询到符合时间范围的记录。

备注:内容来源于stack exchange,提问作者user29789874

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 11:38:11