Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the proper way to handle JDBC connections with Spring and DBCP?

I'm using the Spring MVC to build a thin layer on top of a SQL Server database. When I began testing, it seems that it doesn't handle stress very well :). I'm using Apache Commons DBCP to handle connection pooling and the data source.

When I first attempted ~10-15 simultaneous connections, it used to hang and I'd have to restart the server (for dev I'm using Tomcat, but I'm gonna have to deploy on Weblogic eventually).

These are my Spring bean definitions:

<bean id="dataSource" destroy-method="close"
      class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
    <property name="url" value="[...]"/>
    <property name="username" value="[...]" />
    <property name="password" value="[...]" />
</bean>

<bean id="partnerDAO" class="com.hp.gpl.JdbcPartnerDAO">
    <constructor-arg ref="dataSource"/>
</bean>

<!-- + other beans -->

And this is how I use them:

// in the DAO
public JdbcPartnerDAO(DataSource dataSource) {
    jdbcTemplate = new JdbcTemplate(dataSource);
}

// in the controller
@Autowired
private PartnerDAO partnerDAO;

// in the controller method
Collection<Partner> partners = partnerDAO.getPartners(...);

After reading around a little bit, I found the maxWait, maxActive and maxIdle properties for the BasicDataSource (from GenericObjectPool). Here comes the problem. I'm not sure how I should set them, performance-wise. From what I know, Spring should be managing my connections so I shouldn't have to worry about releasing them.

<bean id="dataSource" destroy-method="close"
      class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
    <property name="url" value="[...]"/>
    <property name="username" value="[...]" />
    <property name="password" value="[...]" />
    <property name="maxWait" value="30" />
    <property name="maxIdle" value="-1" />
    <property name="maxActive" value="-1" />
</bean>

First, I set maxWait, so that it wouldn't hang and instead throw an exception when no connection was available from the pool. The exception message was:

Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object

There are some long-running queries, but the exception was thrown regardless of the query complexity.

Then, I set maxActive and maxIdle so that it wouldn't throw the exceptions in the first place. The default values are 8 for maxActive and maxIdle (I don't understand why); if I set them to -1 there are no more exceptions thrown and everything seems to work fine.

Considering that this app should support a large number of concurrent requests is it ok to leave these settings to infinite? Will Spring actually manage my connections, considering the errors I was receiving? Should I switch to C3P0 considering it's kinda dead?

like image 291
Alex Ciminian Avatar asked Aug 19 '10 19:08

Alex Ciminian


People also ask

How is database connection managed in Spring?

It binds a JDBC connection from the specified data source to the currently executing thread, potentially allowing for one thread connection per data source. Application code is required to retrieve the JDBC connection via DataSourceUtils. getConnection(DataSource) instead of Java EE's standard DataSource.

Which of the following approaches does Spring framework provide for JDBC database access?

Spring framework provides the following approaches for JDBC database access: JdbcTemplate. NamedParameterJdbcTemplate. SimpleJdbcTemplate.

What is JDBC connection pooling why we need connection pooling in Spring Boot?

A connection pooling module maintains it as a layer on top of any standard JDBC driver product. It increases the speed of data access and reduces the number of database connections for an application. It also improves the performance of an application.

How does DBCP connection pool work?

The connection user name to be passed to our JDBC driver to establish a connection. The connection password to be passed to our JDBC driver to establish a connection. The connection URL to be passed to our JDBC driver to establish a connection. The fully qualified Java class name of the JDBC driver to be used.


1 Answers

DBCP maxWait parameter should be defined in milliseconds. 30 ms is very low value, consider increasing it to 30000 ms and try again.

like image 80
stoweesh Avatar answered Sep 27 '22 15:09

stoweesh