具有JDBCTemplate的BasicDataSource未按预期汇集连接

时间:2012-03-20 13:00:49

标签: spring jdbctemplate apache-commons-dbcp

我正在尝试使用BasicDataSource在spring应用程序中与JDBCTemplate池连接。从我读过的所有内容来看,这应该非常简单:只需在XML中配置BasicDataSource,将数据源注入bean,然后在setter方法中创建一个新的JDBCTemplate。

当我这样做时,我注意到我的表现非常糟糕。然后我切换到Spring的SingleConnectionDataSource,只是为了看看会发生什么,我的表现得到了更好 。我开始使用分析器工具进行调查,我注意到在使用BasicDataSource时,正在为每个查询创建一个新连接。

进一步调查,我可以看到查询完成后连接的关闭位置。特别是在Spring的DataSourceUtil类中:

public static void doReleaseConnection(Connection con, DataSource dataSource) throws SQLException {
    if (con == null) {
        return;
    }

    if (dataSource != null) {
        ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
        if (conHolder != null && connectionEquals(conHolder, con)) {
            // It's the transactional Connection: Don't close it.
            conHolder.released();
            return;
        }
    }

    // Leave the Connection open only if the DataSource is our
    // special SmartDataSoruce and it wants the Connection left open.
    if (!(dataSource instanceof SmartDataSource) || ((SmartDataSource) dataSource).shouldClose(con)) {
        logger.debug("Returning JDBC Connection to DataSource");
        con.close();
    }
}

我注意到的是'SmartDataSource'有一些特殊的逻辑,它使连接保持打开状态。这部分解释了我所看到的行为:由于SingleConnectionDataSource实现了SmartDataSource,因此连接未关闭。但是,我认为通过使用BasicDataSource,连接上的close()方法只会返回到池的连接。但是,当我查看我的探查器中发生的事情时,实际上是在我的sybase连接上调用close方法:不是像我希望看到的任何类型的“池连接包装器”。

最后一件事(这是我现在要研究的内容):我使用TransactionTemplate进行一些查询(涉及对数据库的提交),但是简单查询不在transactionTemplate中。我不知道这是否与问题有关。

编辑1:

好的,在稍微关闭项目之后,终于有了更多时间进行调查,这是一个非常简单的测试,显示问题

    public class DBConnectionPoolTest {

@Autowired
@Qualifier("myDataSource")
private DataSource dataSource;

@Test
public void test() throws Exception{
    JdbcTemplate template = new JdbcTemplate(dataSource);
    StopWatch sw = new StopWatch();
    sw.start();
    for(int i=0; i<1000; i++){
        template.queryForInt("select count(*) from mytable"); 
    }
    sw.stop();

    System.out.println("TIME: " + sw.getTotalTimeSeconds() + " seconds");   
}}

以下是我的两个数据源配置:

<bean id="myDataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
    <property name="driverClassName" value="${db.driver}" />
    <property name="url" value="${db.url}" />
    <property name="username" value="${db.username}" />
    <property name="password" value="${db.password}" />
</bean>

<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${db.driver}" />
    <property name="url" value="${db.url}" />
    <property name="username" value="${db.username}" />
    <property name="password" value="${db.password}" />
</bean>

当我使用第一个配置运行测试时,大约需要2.1秒。当我使用第二种配置运行它时,大约需要4.5秒。我在BasicDataSource上尝试了各种参数,比如设置maxActive = 1和testOnBorrow = false,但没有什么区别。

1 个答案:

答案 0 :(得分:0)

我认为我的问题是我的sybase的jdbc库已经过时了。