带有 Quartz 和 Tomcat 数据源的 SpringBoot:驱动程序的 Blob 表示是不受支持的类型:oracle.sql.BLOB

SpringBoot with Quartz and Tomcat datasource: Driver's Blob representation is of an unsupported type: oracle.sql.BLOB

我正在使用 SpringBoot 1.4.5 和 quartz 来调度 Tomcat 的 context.xml 中配置的数据源,该数据源通过 JndiDataSource 作为 bean 注入以连接到 Oracle 10g 数据库。

下面是相关依赖,包括Oracle驱动,我使用的是SpringBoot提供的依赖管理:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>2.2.1</version>
        </dependency>
            <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>oracle-ojdbc7</artifactId>
            <version>12.1.0-2</version>
        </dependency>

这是context.xml中Tomcat配置的DataSource(占位符属性在catalina.properties中定义):

<Resource name="${tomcat.dbpool.ups.quartz.resourcename}" auth="Container"
                type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
                url="${tomcat.dbpool.ups.quartz.connectionurl}"
                username="${tomcat.dbpool.ups.quartz.username}"
                password="${tomcat.dbpool.ups.quartz.password}"
                maxTotal="${tomcat.dbpool.ups.quartz.maxTotal}"
                maxIdle="${tomcat.dbpool.ups.quartz.maxIdle}"
                minIdle="${tomcat.dbpool.ups.quartz.minIdle}"
                maxWaitMillis="${tomcat.dbpool.ups.quartz.maxWaitMillis}"
                validationQueryTimeout="${tomcat.dbpool.ups.quartz.validationQueryTimeout}"
                testWhileIdle="true"
                removeAbandonedOnMaintenance="true"
                timeBetweenEvictionRunsMillis="${tomcat.dbpool.ups.quartz.timeBetweenEvictionRunsMillis}"
                minEvictableIdleTimeMillis="${tomcat.dbpool.ups.quartz.minEvictableIdleTimeMillis}"
                />

数据源bean配置和quartz必需的bean:

@Bean
    public JobFactory jobFactory(final ApplicationContext applicationContext) {
        final AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
        jobFactory.setApplicationContext(applicationContext);
        return jobFactory;
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(@Qualifier("quartzDataSource") final DataSource quartzDS,
                                                     final JobFactory jobFactory,
                                                     @Qualifier("loansAppTrigger") final Trigger jobTrigger) throws IOException {
        final SchedulerFactoryBean factory = new SchedulerFactoryBean();
        // this allows to update triggers in DB when updating settings in config file:
        factory.setOverwriteExistingJobs(true);
        factory.setDataSource(quartzDS);
        factory.setJobFactory(jobFactory);

        factory.setQuartzProperties(quartzProperties());
        factory.setTriggers(jobTrigger);

        return factory;
    }

    @Bean(name = "quartzDataSource")
    @Profile("!local")
    public DataSource jndiDataSource() {
        JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
        DataSource dataSource = dataSourceLookup.getDataSource("java:comp/env/jdbc/QUARTZ");
        return dataSource;
    }

    @Bean
    public Properties quartzProperties() throws IOException {
        final PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();
    }

    @Bean
    public JobDetailFactoryBean checkUnconfirmedApplicationsJobDetail() {
        return createJobDetail(CheckUnconfirmedApplicationsJob.class);
    }

    @Bean(name = "loansAppTrigger")
    public SimpleTriggerFactoryBean unconfirmedLoansApplicationsTrigger(
            @Qualifier("checkUnconfirmedApplicationsJobDetail") final JobDetail jobDetail,
            @Value("${ups.loan.check.pending.apps.frequency}") final long frequency) {
        return createTrigger(jobDetail, frequency);
    }

    private static JobDetailFactoryBean createJobDetail(final Class jobClass) {
        final JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
        factoryBean.setJobClass(jobClass);
        // job has to be durable to be stored in DB:
        factoryBean.setDurability(true);
        return factoryBean;
    }

    private static SimpleTriggerFactoryBean createTrigger(final JobDetail jobDetail, final long pollFrequencyMs) {
        final SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean();
        factoryBean.setJobDetail(jobDetail);
        factoryBean.setStartDelay(0L);
        factoryBean.setRepeatInterval(pollFrequencyMs);
        factoryBean.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
        // in case of misfire, ignore all missed triggers and continue :
        factoryBean.setMisfireInstruction(SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT);

        return factoryBean;
    }

以及 quartz.properties 文件中的以下属性:

org.quartz.scheduler.instanceName=scheduler
org.quartz.scheduler.instanceId=AUTO
org.quartz.threadPool.threadCount=5
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.misfireThreshold=60000

org.quartz.jobStore.isClustered=true
org.quartz.jobStore.clusterCheckinInterval=20000

当我在 Tomcat 8 上部署它时,出现以下错误:

org.quartz.JobPersistenceException:无法存储作业:驱动程序的 Blob 表示是不支持的类型:oracle.sql.BLOB

在 Tomcat 的 lib 文件夹中,我有 oracle-ojdbc7-12.1.0-2.jar 驱动程序。

能否请您检查是否存在任何重复的 oracle-ojdbc JAR 文件? JAR 应该只位于一个位置:在 WEB-INF/lib 或 tomcat/lib