Spring 带有JDBCTemplate的BasicDataSource未按预期共享连接

Spring 带有JDBCTemplate的BasicDataSource未按预期共享连接,spring,jdbctemplate,apache-commons-dbcp,Spring,Jdbctemplate,Apache Commons Dbcp,我正试图在spring应用程序中使用BasicDataSource来共享与JDBCTemplate的连接。从我读到的所有内容来看,这应该非常简单:只需在XML中配置BasicDataSource,将数据源注入bean,然后在setter方法中创建一个新的JDBCTemplate 当我这么做的时候,我注意到我的表现很糟糕。然后我切换到Spring的SingleConnectionDataSource,只是想看看会发生什么,我的性能得到了很大的提高。我开始使用探查器工具进行调查,发现在使用Basic

我正试图在spring应用程序中使用BasicDataSource来共享与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()方法将只返回到池的连接。然而,当我查看探查器中发生的情况时,close方法实际上是在sybase连接上被调用的:而不是我所期望看到的任何类型的“池连接包装器”

最后一件事(这是我现在要研究的):我使用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");   
}}
公共类DBConnectionPoolTest{
@自动连线
@限定符(“myDataSource”)
私有数据源;
@试验
public void test()引发异常{
JdbcTemplate=新的JdbcTemplate(数据源);
秒表sw=新秒表();
sw.start();

对于(int i=0;i我认为我的例子中的问题是我的sybase jdbc库已经过时了。

向我们展示您的配置,以及配置和注入数据源和JdbcTemplate的位置。
<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>