У меня есть пакетный проект Spring, который подключается к базе данных Oracle SQL и позволяет экспортировать / импортировать некоторые данные с помощью файлов xls.
В своей работе я сначала делаю удаление в таблице перед импортомданные.Иногда задание не выполнялось из-за проблем с импортом в xls.Например: если у меня есть дубликаты строк, у меня будет SQLException для дубликатов, когда задание будет вставлять строки в базу данных.
Я хочу просто ничего не фиксировать (особенно часть удаления).Если задание выполнено успешно -> зафиксировать Если задание не выполнено -> откат
Итак, я обнаружил, что для «setAutocommit» необходимо установить значение false.
У меня загружен источник данных в началемоя работа, поэтому я делаю:
dataSource.getConnection().setAutoCommit(false);
Инструкция работает, но когда я запускаю работу, у меня появляется эта ошибка:
ERROR o.s.batch.core.step.AbstractStep -
Encountered an error executing step step_excel_sheet_1551274910254 in job importExcelJob
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'scopedTarget.xlsListener'
defined in class path resource [com/adeo/config/ImportExcelConfig.class]:
Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [org.springframework.batch.core.StepExecutionListener]:
Factory method 'xlsListener' threw exception; nested exception is
java.lang.NoClassDefFoundError: oracle/xdb/XMLType
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
Конфигурация задания:
@Configuration
public class ImportExcelConfig {
private static final Logger LOG = LoggerFactory.getLogger("ImportExcelConfig");
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Resource(name = "dataSource")
private DataSource dataSource;
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Bean(name = "importExcelJob")
public Job importExcel(@Qualifier("xlsPartitionerStep") Step xlsPartitionerStep) throws Exception {
return jobBuilderFactory.get("importExcelJob").start(xlsPartitionerStep).build();
}
@Bean(name = "xlsPartitionerStep")
public Step xlsPartitionerStep(@Qualifier("xlsParserSlaveStep") Step xlsParserSlaveStep, XlsPartitioner xlsPartitioner){
return stepBuilderFactory.get("xls_partitioner_step_builder")
.partitioner(xlsParserSlaveStep)
.partitioner("xls_partitioner_step_builder",XlsPartitioner)
.gridSize(3)
.build();
}
@Bean(name = "xlsParserSlaveStep")
@StepScope
public Step xlsParserSlaveStep(@Qualifier("step") Step step,XlsSheetPartitioner xlsPartitioner) throws Exception {
return stepBuilderFactory.get("sheet_partitioner_"+System.currentTimeMillis())
.partitioner(step)
.partitioner("sheet_partitioner_"+System.currentTimeMillis(),XlsPartitioner)
.gridSize(3)
.build();
}
@Bean(name = "step")
@StepScope
public Step step(@Qualifier("xlsReader") PoiItemReader xlsReader,
@Qualifier("jdbcWriter") ItemWriter jdbcWriter,
@Qualifier("xlsListener") StepExecutionListener xlsListener
) throws Exception {
return ((SimpleStepBuilder)stepBuilderFactory
.get("step_excel_sheet_"+System.currentTimeMillis())
.<Object, Map>chunk(1000)
.reader(xlsReader)
.writer(jdbcWriter)
.listener(xlsListener)
).build();
}
@Bean(name = "xlsListener")
@StepScope
@DependsOn
public StepExecutionListener xlsListener() {
XlsStepExecutionListener listener = new xlsStepExecutionListener();
listener.setDataSource(dataSource);
listener.afterPropertiesSet();
return listener;
}
@Bean(name = "jdbcWriter")
@StepScope
@DependsOn
public ItemWriter<Map> jdbcWriter(@Value("#{stepExecutionContext[sheetConfig]}") SheetConfig sheetConfig) throws IOException, ClassNotFoundException {
JdbcBatchItemWriter<Map> writer = new JdbcBatchItemWriter<>();
writer.setItemPreparedStatementSetter(preparedStatementSetter());
String sql = sheetConfig.getSqlInsert().replaceAll("#TABLE#", sheetConfig.getTable());
LOG.info(sql);
writer.setSql(sql);
writer.setDataSource(dataSource);
writer.afterPropertiesSet();
return writer;
}
@Bean
@StepScope
public ItemPreparedStatementSetter preparedStatementSetter(){
return new ItemPreparedStatementSetter();
}
@Bean
public ItemProcessor testProcessor() {
return new TestProcessor();
}
@Bean(name = "xlsReader")
@StepScope
@DependsOn
public PoiItemReader xlsReader(@Value("#{stepExecutionContext[sheetConfig]}") SheetConfig sheetConfig,
@Value("#{stepExecutionContext[xls]}") File xlsFile) throws IOException {
PoiItemReader reader = new PoiItemReader();
reader.setResource(new InputStreamResource(new PushbackInputStream(new FileInputStream(xlsFile))));
reader.setRowMapper(mapRowMapper());
reader.setSheet(sheetConfig.getSheetIndex());
reader.setLinesToSkip(sheetConfig.getLinesToSkip());
return reader;
}
@Bean
@StepScope
@DependsOn
public RowMapper mapRowMapper() throws IOException {
return new MapRowMapper();
}
}
Слушатель:
public class XlsStepExecutionListener implements StepExecutionListener, InitializingBean {
private final static Logger LOGGER = LoggerFactory.getLogger(XlsStepExecutionListener.class);
@Value("#{stepExecutionContext[sheetConfig]}")
private SheetConfig config;
@Value("#{jobParameters['isFull']}")
private boolean isFull;
@Value("#{stepExecutionContext[supp]}")
private String supp;
private DataSource dataSource;
@Override
public void afterPropertiesSet() {
Assert.notNull(dataSource, "dataSource must be provided");
}
@Override
public void beforeStep(StepExecution stepExecution) {
LOGGER.info("Start - Import sheet {}", config.sheetName);
dataSource.getConnection().setAutoCommit(false);
JdbcTemplate jt = new JdbcTemplate(dataSource);
if(config.sqlDelete != null){
//DELETE DATA
LOGGER.info("beforeStep - PURGE DATA"+config.getSqlDelete().replaceAll("#TABLE#", config.getTable()));
jt.update(config.getSqlDelete().replaceAll("#TABLE#", config.getTable()),supp);
}
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
LOGGER.info ("End - Import sheet {}",config.sheetName);
//TODO :
//If status failed -> rollback, if status success : commit
return ExitStatus.COMPLETED;
}
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}
В pom.xml у меня есть оракул jar:
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
Я вижу, что класс XMLType находится в другом банкеOracle, но я не знаю, почему мне нужно добавить этот jar, когда я просто изменяю режим автоматической фиксации?Кроме того, я вижу, что для ВСЕГО метода, который я могу вызвать из getConnection (). XXXX, происходит то же исключение.Так что это не относится к автоматической фиксации.
Спасибо