如何提前初始化c3p0池?

How can I initialize the c3p0 pool in advance?

我需要做大量的实时异步查询操作,预期效果如第一条日志输出的"second asynchronous query"范围

但实际上,第一个异步查询操作总是会初始化"c3p0 pool",效果就像第一个日志输出中的"first asynchronous query"

因为"c3p0 pool"现在才开始,所以网页第一次查询会有明显的停顿,后面的查询不会停顿。

如何在第一次查询操作前初始化"c3p0 pool",避免第一次查询暂停?

日志输出:


Completed Tomcat initialization...
============================================

[2019-04-06 11:29:20,273] Artifact Gradle : humingk : humingk-1.0-SNAPSHOT.war (exploded): Artifact is deployed successfully
[2019-04-06 11:29:20,273] Artifact Gradle : humingk : humingk-1.0-SNAPSHOT.war (exploded): Deploy took 28,470 milliseconds
11:29:22.840 [http-nio-8080-exec-4] DEBUG org.apache.shiro.web.servlet.SimpleCookie - Found 'shiro-cookie' cookie value [7JUK8JeReLqOLB4SgQJ/5AOUuG***********************=]
11:29:22.900 [http-nio-8080-exec-4] DEBUG org.apache.shiro.mgt.DefaultSecurityManager - Found remembered PrincipalCollection.  Adding to the context to be used for subject construction by the SubjectFactory.

=============Start my first asynchronous query===============

====start initializing c3p0 pool=== (Seriously I don't want to delay it until now)

11:47:14.830 [http-nio-8080-exec-7] INFO  com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 3, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 1bqz1r5a11us7ntzkwpkmf|1b23856e, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.cj.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 1bqz1r5a11us7ntzkwpkmf|1b23856e, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/douban_movie?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&nullCatalogMeansCurrent=true, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 30, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 10, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
11:47:14.877 [http-nio-8080-exec-7] DEBUG com.mchange.v2.cfg.MConfig - The configuration file for resource identifier '/mchange-commons.properties' could not be found. Skipping.
11:47:14.877 [http-nio-8080-exec-7] DEBUG com.mchange.v2.cfg.MConfig - The configuration file for resource identifier '/mchange-log.properties' could not be found. Skipping.
11:47:14.877 [http-nio-8080-exec-7] DEBUG com.mchange.v2.cfg.MConfig - The configuration file for resource identifier '/c3p0.properties' could not be found. Skipping.
11:47:14.877 [http-nio-8080-exec-7] DEBUG com.mchange.v2.cfg.MConfig - The configuration file for resource identifier 'hocon:/reference,/application,/c3p0,/' could not be found. Skipping.
11:47:14.877 [http-nio-8080-exec-7] WARN  com.mchange.v2.resourcepool.BasicResourcePool - Bad pool size config, start 3 < min 10. Using 10 as start.
11:47:14.893 [http-nio-8080-exec-7] DEBUG com.mchange.v2.resourcepool.BasicResourcePool - com.mchange.v2.resourcepool.BasicResourcePool@62ffa7a0 config: [start -> 10; min -> 10; max -> 30; inc -> 3; num_acq_attempts -> 3; acq_attempt_delay -> 1000; check_idle_resources_delay -> 0; max_resource_age -> 0; max_idle_time -> 0; excess_max_idle_time -> 0; destroy_unreturned_resc_time -> 0; expiration_enforcement_delay -> 0; break_on_acquisition_failure -> false; debug_store_checkout_exceptions -> false; force_synchronous_checkins -> false]
11:47:14.893 [http-nio-8080-exec-7] DEBUG com.mchange.v2.c3p0.impl.C3P0PooledConnectionPoolManager - Created new pool for auth, username (masked): 'ro******'.
11:47:14.893 [http-nio-8080-exec-7] DEBUG com.mchange.v2.resourcepool.BasicResourcePool - acquire test -- pool size: 0; target_pool_size: 10; desired target? 1
11:47:14.893 [http-nio-8080-exec-7] DEBUG com.mchange.v2.resourcepool.BasicResourcePool - awaitAvailable(): [unknown]

====finish initializing c3p0 pool=== 

11:47:15.564 [http-nio-8080-exec-7] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
11:47:15.595 [http-nio-8080-exec-7] DEBUG org.mybatis.spring.SqlSessionUtils - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1e5d3666]
11:47:15.638 [http-nio-8080-exec-7] DEBUG org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@526aab0d [wrapping: com.mysql.cj.jdbc.ConnectionImpl@47a7bea5]] will be managed by Spring
11:47:15.646 [http-nio-8080-exec-7] DEBUG org.humingk.movie.mapper.MovieMapper.selectMoviesByNameStart - ==>  Preparing: select movie.* from movie where movie.name like CONCAT('',?,'%') order by movie.rate desc limit 10 
11:47:15.717 [http-nio-8080-exec-7] DEBUG org.humingk.movie.mapper.MovieMapper.selectMoviesByNameStart - ==> Parameters: a(String)
11:47:15.798 [http-nio-8080-exec-7] DEBUG org.humingk.movie.mapper.MovieMapper.selectMoviesByNameStart - <==      Total: 10
11:47:15.814 [http-nio-8080-exec-7] DEBUG org.mybatis.spring.SqlSessionUtils - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1e5d3666]
11:47:15.814 [http-nio-8080-exec-7] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1e5d3666]
11:47:15.814 [http-nio-8080-exec-7] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1e5d3666]
11:47:15.814 [http-nio-8080-exec-7] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1e5d3666]

=================finish my first asynchronous query======================

=================Start my second asynchronous query===============

11:49:13.276 [http-nio-8080-exec-1] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
11:49:13.276 [http-nio-8080-exec-1] DEBUG org.mybatis.spring.SqlSessionUtils - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@50729ffd]
11:49:13.276 [http-nio-8080-exec-1] DEBUG org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@250d6429 [wrapping: com.mysql.cj.jdbc.ConnectionImpl@47a7bea5]] will be managed by Spring
11:49:13.276 [http-nio-8080-exec-1] DEBUG org.humingk.movie.mapper.MovieMapper.selectMoviesByNameStart - ==>  Preparing: select movie.* from movie where movie.name like CONCAT('',?,'%') order by movie.rate desc limit 10 
11:49:13.276 [http-nio-8080-exec-1] DEBUG org.humingk.movie.mapper.MovieMapper.selectMoviesByNameStart - ==> Parameters: w(String)
11:49:13.276 [http-nio-8080-exec-1] DEBUG org.humingk.movie.mapper.MovieMapper.selectMoviesByNameStart - <==      Total: 10
11:49:13.276 [http-nio-8080-exec-1] DEBUG org.mybatis.spring.SqlSessionUtils - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@50729ffd]
11:49:13.276 [http-nio-8080-exec-1] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@50729ffd]
11:49:13.276 [http-nio-8080-exec-1] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@50729ffd]
11:49:13.276 [http-nio-8080-exec-1] DEBUG org.mybatis.spring.SqlSessionUtils - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@50729ffd]

=================finish my second asynchronous query======================

more asynchronous query normally like second ...

我的spring-mapper.xml:

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="driverClass" value="${jdbc.driverClassName}"/>
        <property name="maxPoolSize" value="30" />
        <property name="minPoolSize" value="10" />
        <property name="autoCommitOnClose" value="false" />
        <property name="checkoutTimeout" value="10000" />
        <property name="acquireRetryAttempts" value="3" />
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:mybatis/mybatis-config.xml" />
        <property name="typeAliasesPackage" value="org.humingk.movie.entity" />
        <property name="mapperLocations" value="classpath:mapper/*Mapper.xml" />
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
        <property name="basePackage" value="org.humingk.movie.mapper" />
    </bean>

基本上,您需要做的是在您的应用程序初始化后调用 dataSource.getConnection().close()

为 Web 应用程序执行此操作的老派方法是定义 ServletContextListener。对于 Spring 应用程序,您可能需要 ApplicationListener for a ContextRefreshEvent。这可能看起来像...

import com.mchange.v2.c3p0.ComboPooledDataSource

@Component
public DataSourceInitializer implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
       ComboPooledDataSource dataSource = event.getApplicationContext().getBean("dataSource", ComboPooledDataSource.class);
       dataSource.getConnection().close();
    }
}

我只是即兴发挥,当然还没有尝试或编译它,如果不完全正确,我们深表歉意。不过应该差不多了。

另见 ContextRefreshedEvent, ApplicationContext