javaspring-boothibernatetomcatconnection-pooling

How to know DriverManagerDataSource has a connection pool


I have a question about the DriverManagerDataSource in Spring.

Our microservice uses Spring Boot and Hibernate to connect to Druid Database. We use DriverManagerDataSource to create our dataSource instance. From the documentation of DriverManagerDataSource, we know that it does not have a proper connection pool implementation.

However, when we tested the microservice, we can see 10 established TCP connections when we increased the query load to 10 concurrent virtual users, and those 10 connections remained established even after the queries completed. They only reduced to 1 connection after we initiated a new query with only 1 concurrent virtual user.

The above symptom indicates that there is indeed a connection pool established. I am pretty confused at this point: where is this pool coming from?

I tried the test mentioned here, but I got

Datasource = org.springframework.jdbc.datasource.DriverManagerDataSource@xxxx;

(pls ignore the xxxx). The following is a partial pint out of the microservice's startup that shows Tomcat started:

[30m2024-03-12 10:03:27,567[0;39m [34mINFO [0;39m [[34mmain[0;39m] [33morg.apache.juli.logging.DirectJDKLog[0;39m [,] - Starting service [Tomcat]`
[30m2024-03-12 10:03:27,568[0;39m [34mINFO [0;39m [[34mmain[0;39m] [33morg.apache.juli.logging.DirectJDKLog[0;39m [,] - Starting Servlet engine: [Apache Tomcat/9.0.86];

I am not sure if Tomcat JDBC's connection pool automatically kicked in?


Solution

  • org.springframework.jdbc.datasource.DriverManagerDataSource is not a connection pool. It is a simple implementation of javax.sql.DataSource which was autowired to the spring boot application.

    Simple implementation of the standard JDBC DataSource interface, configuring the plain old JDBC DriverManager via bean properties, and returning a new Connection from every getConnection call.

    NOTE: This class is not an actual connection pool; it does not actually pool Connections. It just serves as simple replacement for a full-blown connection pool, implementing the same standard interface, but creating new Connections on every call.

    Useful for test or standalone environments outside a Jakarta EE container, either as a DataSource bean in a corresponding ApplicationContext or in conjunction with a simple JNDI environment. Pool-assuming Connection.close() calls will simply close the Connection, so any DataSource-aware persistence code should work.

    This DriverManagerDataSource class was originally designed alongside Apache Commons DBCP and C3P0, featuring bean-style BasicDataSource/ComboPooledDataSource classes with configuration properties for local resource setups. For a modern JDBC connection pool, consider HikariCP instead, exposing a corresponding HikariDataSource instance to the application.

    If you use Hibernate, you should read

    Chapter 1.

    1.1. Connecting Hibernate connects to databases on behalf of your application. It can connect through a variety of mechanisms, including:

    Stand-alone built-in connection pool

    javax.sql.DataSource

    Connection pools, including support for two different third-party opensource JDBC connection pools:

    c3p0

    proxool

    Application-supplied JDBC connections. This is not a recommended approach and exists for legacy reasons

    Note: The built-in connection pool is not intended for production environments.

    Hibernate obtains JDBC connections as needed though the ConnectionProvider interface which is a service contract. Applications may also supply their own ConnectionProvider implementation to define a custom approach for supplying connections to Hibernate (from a different connection pool implementation, for example).

    Chapter 3.3 JDBC Connections

    Hibernate's own connection pooling algorithm is however quite rudimentary. It is intended to help you get started and is not intended for use in a production system or even for performance testing. You should use a third party pool for best performance and stability. Just replace the hibernate.connection.pool_size property with connection pool specific settings. This will turn off Hibernate's internal pool.

    Hibernate data sources

    If you are not configured data sources then Hibernate will use

    hibernate.connection.provider_class = org.hibernate.connection.DriverManagerConnectionProvider
    

    This connection provider has in-built rudimentary connection pool for which you can set a hibernate.connection.pool_size, but it is used only for development purposes. Never use it in the production environment.

    Hibernate connection pool

    In your hibernate configuration implicitly used DriverManagerConfigurationProvider. This provider used by default unless you configured it with property connection.provider_class.

    This provider also implements a very rudimentary connection pool.

    What it means "rudimentary connection pool". If you run your application you can see in the logs

       [DriverManagerConnectionProvider] >Using Hibernate built-in connection pool (not for production use!)
       [DriverManagerConnectionProvider] >Hibernate connection pool size: 20
    

    You can also set this value via hibernate configuration property connection.pool_size. But it doesn't limit you to the maximum opened connections count. You can open as many as you need connections while pool is empty. The provider will keep them open as it returns connections to pool on closeConnection unless the current pool size not exceeds the value in the property connection.pool_size. Once current pool size is not empty you cannot open any new connection because the connection provider returns connection from the pool.