Я использую ClassifierCompositeItemWriter для вставки различных типов регистров, хранящихся в одном плоском файле фиксированной длины, и записываю его в базу данных postgres с несколькими JdbcBatchItemWriters, каждый из которых находится в другой таблице, все это внутри шага, а затем добавляем подпружиненный пакет.задание работает нормально, но при активации транзакций они не откатываются в случае исключения.
Например, у меня есть плоский файл из 32 строк, 1 строка - запись заголовка, а затем я вставляю ее в таблицу заголовков., затем есть 30 обычных записей и 1 запись нижнего колонтитула (по порядку), затем в записи 29 обычной записи происходит сбой с исключением преобразования базы данных (ошибка, созданная для тестирования), а затем он завершается с состоянием сбоя задания, и этохорошо, но когда я смотрю на базу данных, я нашел 1 запись для заголовка, 29 записей для обычных данных (кроме одной с ошибкой) и без записи нижнего колонтитула, но я надеюсь, что откат транзакции, что 1 запись для заголовка и другие 29 записей,но они все еще яn база данных после отката исключений.
Я не знаю, ошибаюсь ли я, и транзакции в весеннем пакете не работают таким образом, или это ошибка в моей конфигурации, или что.
Воткод для ClassifierCompositeItemWriter и одного средства записи элементов, аналогичных другим:
public ClassifierCompositeItemWriter<DTOBase> altasOffWriterClassifier(DataSource dataSource) {
BackToBackPatternClassifier classifier = new BackToBackPatternClassifier();
classifier.setRouterDelegate(dtoWriterClassifier);
classifier.setMatcherMap(new HashMap<String, JdbcBatchItemWriter<? extends DTOBase>>() {
private static final long serialVersionUID = -1247536568421993759L;
{
put(DTOHeader.class.getTypeName(), headerWriter());
put(DTOData.class.getTypeName(), dataWriter());
put(DTOFooter.class.getTypeName(), footerWriterFin());
}});
ClassifierCompositeItemWriter<DTOBase> writer = new ClassifierCompositeItemWriter<>();
writer.setClassifier(classifier);
return writer;
}
@Bean
public JdbcBatchItemWriter<DTOAltaOFF> altaOffWriter() {
return new JdbcBatchItemWriterBuilder<DTOData>()
.dataSource(dataSource)
.sql("insert into tabla(ticket, identificador, fecha_alta_operacion, "
+ " ordenante, numero, moneda, cif, importe_emisor, "
+ " estado, telefono_destino, fecha_caducidad_hal, concepto, cabecera_num_orden_fichero) "
+ " VALUES (:ticket,:identificador,to_timestamp(:fechaAltaOperacion,'DDMMYYYYHH24MISS'), "
+ " :ordenante,:numero,:moneda,:cif,(cast(:importeEmisor as double precision)/100), "
+ " :estado,:telefonoDestino,to_timestamp(:fechaCaducidadHal,'DDMMYYYYHH24MISS'),:concepto,:idCabecera) ")
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
.build();
}
мои классы конфигурации:
@Configuration
@EnableBatchProcessing
@Import({ DataSourceConfig.class })
@PropertySource("classpath:batch.properties")
@ComponentScan({ "..."})
public class BatchConfiguration {
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Autowired
public JobRepository jobRepository;
@Autowired
public DataSource dataSource;
@Bean
public JdbcTemplate getJdbcTemplate() {
return new JdbcTemplate(dataSource);
}
@Bean
public TaskExecutor taskExecutor() {
return new SimpleAsyncTaskExecutor();
}
Источник данных
@Configuration
@EnableTransactionManagement
public class DataSourceConfig {
...some @Value...
@Bean(name = "dataSource")
public DriverManagerDataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(datasourceUrl);
dataSource.setUsername(usuario);
dataSource.setPassword(clave);
return dataSource;
}
}
Конфигурация:
@Configuration
@EnableBatchProcessing
@Import({ DataSourceConfig.class })
@PropertySource("classpath:batch.properties")
@ComponentScan({ "..."})
public class BatchConfiguration {
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Autowired
public JobRepository jobRepository;
@Autowired
public DataSource dataSource;
@Bean
public JdbcTemplate getJdbcTemplate() {
return new JdbcTemplate(dataSource);
}
@Bean
public TaskExecutor taskExecutor() {
return new SimpleAsyncTaskExecutor();
}
}
Пользовательский:
@Component
@EnableTransactionManagement
public class CustomBatchConfigurer extends DefaultBatchConfigurer {
private final TaskExecutor taskExecutor;
public CustomBatchConfigurer(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
@Override
protected JobLauncher createJobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(getJobRepository());
jobLauncher.setTaskExecutor(this.taskExecutor);
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
@Autowired
private DataSource dataSource;
@Override
public PlatformTransactionManager getTransactionManager() {
DataSourceTransactionManager tm = new DataSourceTransactionManager();
tm.setDataSource(dataSource);
return tm;
}
}
Любая помощь будет отличной.