在 spring 应用程序上下文中配置 c3p0(intSQL 和时区)

Configure c3p0 in spring application context (intSQL and timezone)

如何在 spring 应用上下文中配置 c3p0?

我是运行mybatis+spring+c3p0+Oracle 11g

extensions 的 c3p0 文档说:

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.

user extensions to configurations 的 c3p0 文档说:

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

因此,我将 spring 应用程序上下文配置为:

<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>

但是没有任何反应,它不会抛出错误,但不会按预期运行。

编辑:这不是个好主意。最好遵循 Shay Elkayam 的方法


经过大量挖掘,我想出了这个完全可用的配置:

<!--
    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>

您在回答中所做的不足以使其发挥作用。

例如,如果您调查 mysql 日志,您会发现 timezone 设置永远不会生效(永远不会执行任何 "set time_zone..." 语句)。

唯一在您的答案中生效的是:preferredTestQuery,您已将其设置为 alter session set current_schema=MY_SCHEMA

这意味着每个 Checkin(几乎在您执行的每个查询之前发生 - 即太多) 也会调用 alter session set current_schema=MY_SCHEMA,这是一个非常糟糕的性能实践...

如果你想在获取连接时执行一些SQL,你需要结合使用ConnectionCustomizer和你创建的extensions映射。 (你可以在他们的文档中看到它here

示例:

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>