BasicDataSource с JDBCTemplate не объединяет соединения, как ожидалось - PullRequest
1 голос
/ 20 марта 2012

Я пытаюсь использовать BasicDataSource для объединения соединений с JDBCTemplate в весеннем приложении. Из всего, что я прочитал, это должно быть действительно просто: просто сконфигурируйте BasicDataSource в XML, вставьте источник данных в bean-компонент, а в методе setter создайте новый JDBCTemplate.

Когда я это сделал, я заметил, что мое выступление было ужасным. Затем я переключился на SpringConnectionDataSource Spring, просто чтобы посмотреть, что произойдет, и моя производительность стала намного лучше. Я начал исследовать с помощью инструмента профилирования и заметил, что при использовании BasicDataSource для каждого запроса создается новое соединение.

Продолжая расследование, я вижу, где закрывается соединение после завершения запроса. В частности, в классе DataSourceUtil Spring:

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 для некоторых моих запросов (связанных с фиксацией в базе данных), но простые запросы не находятся внутри транзакции транзакции. Я не знаю, имеет ли это какое-либо отношение к проблеме или нет.

РЕДАКТИРОВАТЬ 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 голосов
/ 01 апреля 2013

Я думаю, что проблема в моем случае заключалась в том, что мои библиотеки jdbc для sybase были устаревшими.

...