我的简单批处理流程从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永远无法访问异常捕获......
答案 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;