春季批NoClassDefFoundError:oracle / xdb / XMLType

时间:2019-02-27 14:07:32

标签: java oracle groovy spring-batch autocommit

我有一个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中,我有Oracle jar:

<dependency>
    <groupId>com.oracle</groupId>
    <artifactId>ojdbc6</artifactId>
    <version>11.2.0.3</version>
</dependency>

我看到XMLType类在Oracle的另一个jar中,但是我不知道为什么当我简单地修改自动提交模式时需要添加此jar? 另外,我看到,对于我可以从getConnection()。XXXX调用的所有方法,都会发生相同的异常。因此,它不特定于自动提交。

谢谢

0 个答案:

没有答案