Spring启动@Scheduled失败SQL错误:17008,SQLState:08003

时间:2018-04-19 17:53:59

标签: java spring spring-boot scheduled-tasks spring-transactions

这是在here中再次提出的类似问题,这看起来是@Schdeuled不能与@Transaction一起使用的问题。 但是,这有点不同,可能是我的代码处理事务的问题。

我正在运行每天启动的调度程序(DailyScheduler.processDailyScheduler())并因以下错误而失败

  

SQL错误:17008,SQLState:08003   javax.persistence.PersistenceException:   org.hibernate.exception.JDBCConnectionException:无法执行   查询   org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692)     在   org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602)     在   org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:492)   引起:java.sql.SQLRecoverableException:Closed Connection:next

我还有一个控制器(DailyController.processDailyJob),它完全执行相同的工作,但是当我使用相同的输入运行时,它会成功。

我不明白为什么我的调度程序无法通过且控制器始终有效。

对此的任何帮助将不胜感激! 谢谢!

DailyScheduler:

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class DailyScheduler {

    @Autowired
    DailyService dailyService;

    @Scheduled(cron = "${daily.scheduler.cron}")
    public void processDailyScheduler() {

            log.info("DailyScheduler starts");
            dailyService.processDailyJob(new Date());
            log.info("DailyScheduler finishes");
    }
}

DailyController:

@Slf4j
@RestController
@ApiIgnore
public class DailyController {

    @Autowired
    DailyService dailyService;

    @RequestMapping(value = {"/v1/daily/job/{jobDate}"}, method = RequestMethod.POST)
    public ResponseEntity<String> processDailyJob(@PathVariable("jobDate") String jobDate,
                                                   @RequestHeader(SIFAuthorization.AUTHORIZATION) String authorizationToken)
            throws Exception {

        SimpleDateFormat dateFormatter =new SimpleDateFormat("dd-MMM-yyyy");
        Date targetDate =dateFormatter.parse(jobDate);

        dailyService.processDailyJob(targetDate);

        return new ResponseEntity<>("Daily Job Processed.", HttpStatus.OK);
    }

}

DailyServiceImpl:

@Slf4j
@Service
public class DailyServiceImpl implements DailyService {

    @Autowired
    private UserServiceRepository userServiceRepository;

    @Override
    public Integer processDailyJob(Date targetDate) {
        userServiceRepository.findUser(targetDate);
    }

 }

UserServiceRepository:

@Transactional(readOnly = true)
public interface UserServiceRepository extends JpaRepository<UserDailySummary, String> {

     UserDailySummary findUser(Date targetDate);
}

的DBConfig:

@Configuration
@Profile("!test")
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "dbEntityManagerFactory",
        transactionManagerRef = "dbTransactionManager",
        basePackages = {"com.org.dub.mmm"})
@EnableConfigurationProperties(DbProperties.class)
@Slf4j
public class DatabaseConfig {
    @Autowired
    private DbProperties dbProperties;

    @Bean(name = "dataSource")
    @Primary
    public DataSource dataSource() {

        PoolProperties poolProperties = new PoolProperties();
        poolProperties.setUrl(dbProperties.getJdbcUrl());
        poolProperties.setDriverClassName(dbProperties.getDriverClassName());
        poolProperties.setUsername(dbProperties.getUser());
        poolProperties.setPassword(dbProperties.getPassword());

        // override the default value
        poolProperties.setTestOnBorrow(true);
        poolProperties.setTestWhileIdle(true);
        poolProperties.setValidationQuery(dbProperties.getValidationQuery());

        poolProperties.setRemoveAbandoned(true);

        DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource(poolProperties);

        return dataSource;
    }

    @Bean
    PlatformTransactionManager dbTransactionManager() {
        return new JpaTransactionManager(dbEntityManagerFactory().getObject());
    }

    @Bean
    @Primary
    LocalContainerEntityManagerFactoryBean dbEntityManagerFactory() {

        LocalContainerEntityManagerFactoryBean factoryBean = null;

        HibernateJpaVendorAdapter vendorAdapter =
                new HibernateJpaVendorAdapter();
        vendorAdapter.setDatabase(Database.ORACLE);

        factoryBean = new LocalContainerEntityManagerFactoryBean();
        DataSource dataSource = dataSource();

        factoryBean.setDataSource(dataSource);
        factoryBean.setJpaVendorAdapter(vendorAdapter);
        factoryBean.setJpaProperties(additionalJpaProperties());
        factoryBean.setPackagesToScan(new String[]{"com.org.dub.mmm.domain"});
        factoryBean.afterPropertiesSet();

        return factoryBean;
    }

    Properties additionalJpaProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
        properties.setProperty("hibernate.cache.use_second_level_cache", "true");
        properties.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.EhCacheRegionFactory");

        return properties;
    }
}

1 个答案:

答案 0 :(得分:1)

我认为问题与标志removeAbandoned=true有关。此属性与另一个属性removeAbandonedTimeout结合使用。引用有关的参考:

  

(int)可以删除放弃(使用中)连接之前的超时(以秒为单位)。默认值为60(60秒)。该值应设置为应用程序可能具有的最长运行查询。

所以看起来你的所有abbandoned连接都会在1分钟后删除。