Configure c3p0 in spring application context (intSQL and timezone)

核能气质少年 提交于 2019-12-11 02:05:00

问题


How to configure c3p0 in spring application context?

I am running mybatis + spring + c3p0 + Oracle 11g.

c3p0 documentation for extensions says:

extensions Default: an empty java.util.Map A java.util.Map (raw type) containing the values of any user-defined configuration extensions defined for this DataSource.

c3p0 documentation for user extensions to configurations says:

<extensions>
  <property name="initSql">SET SCHEMA 'foo'</property>
  <property name="timezone">PDT</property>
</extensions>

Therefore, I configured my spring application context as:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
    <property name="jdbcUrl" value="jdbc:oracle:thin:@//databasehost:1527/servicename" />
    <property name="user" ref="database.user" />
    <property name="password" ref="database.password" />
    <property name="extensions">
        <map>
            <entry key="initSql" value="ALTER SESSION SET CURRENT_SCHEMA = MY_SCHEMA" />
            <entry key="timezone" value="UTC" />
        </map>
    </property>
</bean>

However nothing happens, it doesn't throw error but doesn't behave as expected.


回答1:


What you did in your answer is not enough to make it work.

If you investigate your mysql log you will see that the timezone setting never takes effect for example (there will be no "set time_zone..." statement executing ever).

The only thing that takes effect in your answer is: preferredTestQuery which you have set to be alter session set current_schema=MY_SCHEMA.

This means that every Checkin (which happens before almost every query you execute - i.e TOO MUCH) will also call alter session set current_schema=MY_SCHEMA which is a very bad performance practice...

If you want to execute some SQL when the connection is aquired, you need to use a ConnectionCustomizer in combination with the extensions Map you have created. (you can see it written in their documentation here)

Example:

public class ExampleConnectionCustomizer extends AbstractConnectionCustomizer {
    public ExampleConnectionCustomizer () {
    }

    private String getInitSql(String parentDataSourceIdentityToken) {
        return (String)this.extensionsForToken(parentDataSourceIdentityToken).get("initSql");
    }

    public void onAcquire(Connection c, String pdsIdt) {
        String initSql = this.getInitSql(parentDataSourceIdentityToken);
        if(initSql != null) {
            Statement stmt = null;
            try {
                stmt = c.createStatement();
                stmt.executeUpdate(initSql);
            } finally {
                if(stmt != null) {
                    stmt.close();
                }
            }
        }
    }

}  


<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    ....The rest of your properties...
    <property name="preferredTestQuery" value="SELECT 1" /> <!--Much more efficient-->
    <property name="connectionCustomizerClassName" value="yourpackage.ExampleConnectionCustomizer" />
    <!-- extensions -->         
    <property name="extensions">
        <map>
            <entry key="initSql" value="alter session set current_schema=MY_SCHEMA" />
        </map>
    </property>
</bean>



回答2:


EDIT: Not a good idea. Better to follow Shay Elkayam's approach


After lots of digging I came up with this fully working configuration:

<!--
    DataSource with connection polling
    For more details, see: http://www.mchange.com/projects/c3p0/
 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
    <property name="jdbcUrl" value="jdbc:oracle:thin:@//hostaname:1527/servicename" />
    <property name="user" value="user" />
    <property name="password" value="password" />
    <!-- Other DataSource Configuration -->
    <property name="numHelperThreads" value="10" />
    <property name="maxAdministrativeTaskTime" value="10000" />
    <!-- pool sizing -->
    <property name="initialPoolSize" value="3" />
    <property name="minPoolSize" value="10" />
    <property name="maxPoolSize" value="35" />
    <property name="acquireIncrement" value="3" />
    <property name="maxStatements" value="0" />
    <!-- retries -->
    <property name="acquireRetryAttempts" value="30" />
    <property name="acquireRetryDelay" value="1000" /> <!-- 1s -->
    <property name="breakAfterAcquireFailure" value="false" />
    <!-- refreshing connections -->
    <property name="maxIdleTime" value="180" /> <!-- 3min -->
    <property name="maxConnectionAge" value="300" />
    <!-- timeouts and testing -->
    <property name="checkoutTimeout" value="5000" /> <!-- 5s -->
    <property name="idleConnectionTestPeriod" value="60" /> <!-- 60s -->
    <property name="testConnectionOnCheckout" value="true" />
    <property name="testConnectionOnCheckin" value="true" />
    <property name="preferredTestQuery" value="alter session set current_schema=MY_SCHEMA" />
    <!-- extensions -->         
    <property name="extensions">
        <map>
            <entry key="timezone" value="UTC" />
        </map>
    </property>
</bean>


来源:https://stackoverflow.com/questions/33553532/configure-c3p0-in-spring-application-context-intsql-and-timezone

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!