【问题标题】:Spring Batch JdbcBatchItemWriter setSql never throws exceptionSpring Batch JdbcBatchItemWriter setSql 从不抛出异常
【发布时间】:2015-02-02 13:54:02
【问题描述】:

我的简单批处理流程从 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) 我需要进行插入。 但是 EmptyResultDataAccessException 显示在日志控制台上并终止了作业,但是 MySQLWriter.java 永远无法捕获异常...

【问题讨论】:

  • JdbcBatchItemWriter#setSql 不会抛出异常,因为它只会将字符串分配给实例变量。
  • 是的,我知道,但我认为尝试通过 write 方法(之后调用)进行更深层次的尝试。抛出它的方法?重写 write 方法?

标签: sql spring jakarta-ee spring-batch


【解决方案1】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-10
    • 2014-07-27
    • 2017-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-26
    • 2019-09-19
    相关资源
    最近更新 更多