Spring 批量 removeJobExecutions 失败

Spring Batch removeJobExecutions fails

我正在尝试使用 Spring Boot 2.3.3 探索 Spring 批处理,显然测试非常重要

批处理不读取/处理/写入任何内容,我刚刚创建了骨架。

在测试方面我有以下内容

@Autowired
private IntegrationTestsNeeds integrationTestsNeeds;
@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
@Autowired
private JobRepositoryTestUtils jobRepositoryTestUtils;

@AfterEach
void tearDown() throws InterruptedException {
    jobRepositoryTestUtils.removeJobExecutions();
}

@Test
void testUpdateStatisticsBatch() throws Exception {
    JobExecution jobExecution = jobLauncherTestUtils.launchJob();
    ExitStatus exitStatus = jobExecution.getExitStatus();
    Assertions.assertThat(exitStatus).isEqualTo(ExitStatus.COMPLETED);
} 

测试通过但在@AfterEach 方法中出现以下错误

org.springframework.dao.DataIntegrityViolationException: StatementCallback; SQL [delete from BATCH_STEP_EXECUTION]; 
Cannot delete or update a parent row: a foreign key constraint fails (`cvl`.`BATCH_STEP_EXECUTION_CONTEXT`, CONSTRAINT `STEP_EXEC_CTX_FK` FOREIGN KEY (`STEP_EXECUTION_ID`) REFERENCES `BATCH_STEP_EXECUTION` (`STEP_EXECUTION_ID`)); 
nested exception is java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`cvl`.`BATCH_STEP_EXECUTION_CONTEXT`, CONSTRAINT `STEP_EXEC_CTX_FK` FOREIGN KEY (`STEP_EXECUTION_ID`) REFERENCES `BATCH_STEP_EXECUTION` (`STEP_EXECUTION_ID`))

我犯了哪种错误?

我无法重现问题,下面是一个无一例外地通过的示例:

import javax.sql.DataSource;

import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.batch.test.JobRepositoryTestUtils;
import org.springframework.batch.test.context.SpringBatchTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBatchTest
@ContextConfiguration(classes = {MyJobTests.MyJobConfig.class})
public class MyJobTests {

    @Autowired
    private JobLauncherTestUtils jobLauncherTestUtils;
    @Autowired
    private JobRepositoryTestUtils jobRepositoryTestUtils;
    
    @Test
    public void testMyJob() throws Exception {
        JobExecution jobExecution = jobLauncherTestUtils.launchJob();
        ExitStatus exitStatus = jobExecution.getExitStatus();
        Assert.assertEquals(ExitStatus.COMPLETED, exitStatus);
    }

    @After
    public void tearDown() {
        jobRepositoryTestUtils.removeJobExecutions();
    }
    
    @Configuration
    @EnableBatchProcessing
    public static  class MyJobConfig {
        @Bean
        public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) {
            return jobs.get("job")
                    .start(steps.get("step")
                            .tasklet((contribution, chunkContext) -> {
                                System.out.println("hello world");
                                return RepeatStatus.FINISHED;
                            })
                            .build())
                    .build();
        }

        @Bean
        public DataSource dataSource() {
            return new EmbeddedDatabaseBuilder()
                    .setType(EmbeddedDatabaseType.H2)
                    .addScript("/org/springframework/batch/core/schema-drop-h2.sql")
                    .addScript("/org/springframework/batch/core/schema-h2.sql")
                    .build();
        }
    }
}

Spring批处理版本4.2.4

我不知道为什么,但是使用 transactionTemplate 解决了问题。

import org.springframework.transaction.support.TransactionTemplate

@Autowired
private TransactionTemplate transactionTemplate;

@AfterEach
void tearDown() {
    transactionTemplate.execute(ts -> {
        jobRepositoryTestUtils.removeJobExecutions();
        return null;
    });
}

尽管 jdbcTemplate 能够执行删除语句,但由于某种原因无法真正从数据库中删除行。