Spring Batch JdbcBatchItemWriter setSql永远不会抛出异常

时间:2015-02-02 13:54:03

标签: sql spring java-ee spring-batch

我的简单批处理流程从CSV文件中读取并写入MySQL数据库(批处理配置正常并且有效)。

我正在使用JdbcBatchItemWriter的自定义实现来完成这项工作,而我实际上是在我的编写器构造函数中进行更新。

CsvReader.java

@Component
@StepScope
public class EducationCsvReader extends FlatFileItemReader {    
    public final static String CSV_FILE_NAME = "education.csv.file";

    @Value("#{jobParameters['"+ CSV_FILE_NAME +"']}")
    public void setResource(final String csvFileName) throws Exception {
        setResource(
                new FileSystemResource(csvFileName)
        );

    }

    public EducationCsvReader() {
        setLinesToSkip(1);
        setEncoding("UTF-8");
        setStrict(true);
        setLineMapper((line, num) -> {
            String[] values = line.split(";");
            return new Education()
                    .setName(values[2].trim())
                    .setId(Integer.parseInt(values[0].trim()));
        });

    }

}

我的自定义JdbcBatchItemWriter:AbstractJdbcBatchItemWriter.java

public abstract class AbstractJdbcBatchItemWriter<T> extends JdbcBatchItemWriter<T>{

    @Autowired
    public AbstractJdbcBatchItemWriter(String SQL_QUERY) {
        setSql(SQL_QUERY);
    }

    @Autowired
    @Override
    public void setItemSqlParameterSourceProvider(
            @Qualifier("beanPropertyItemSqlParameterSourceProvider") ItemSqlParameterSourceProvider provider){
        super.setItemSqlParameterSourceProvider(provider);
    }

    @Autowired
    @Override
    public void setDataSource(@Qualifier("mysqlDataSource") DataSource dataSource){
        super.setDataSource(dataSource);
    }
}

这是我的编写器实现:MySQLWriter.java

@Component
public class EducationMysqlWriter extends AbstractJdbcBatchItemWriter<Education> {
    public EducationMysqlWriter(){
        super("");
        try {
            setSql("UPDATE ecole SET nom=:name WHERE id=:id");
        } catch (EmptyResultDataAccessException exception){
            setSql("INSERT INTO ecole (nom, id) VALUES (:name, :id");
        }
    }

}

我需要更新行但是如果失败(EmptyResultDataAccessException)我需要做一个Insert。 但是,在日志控制台上显示EmptyResultDataAccessException并终止该作业,但MySQLWriter.java永远无法访问异常捕获......

1 个答案:

答案 0 :(得分:0)

JdbcBatchItemWriter#setSql不会抛出异常,因为除了将字符串分配给实例变量之外,它不会做任何事情。构造函数中的try块与write方法没有任何关系,它在首次实例化项目编写器时执行,而write方法对每个正在处理的项目块执行一次。如果您阅读了堆栈跟踪,我希望您能看到JdbcBatchtemWriter正在执行其write方法并抛出异常。

ItemWriter不会为每一行实例化,因此假设您需要插入一些行并且需要更新一些行,在构造函数中设置sql字符串似乎不是一个好主意。

您可以使用单独的sql字符串覆盖插入的ItemWriter#write方法,但使用mysql upsert syntax使用一个字符串会更容易:

INSERT INTO ecol (nom, id) VALUES (:name, :id)
  ON DUPLICATE KEY UPDATE nom = :name;