How do I use DataSource instead of DriverManager?

Switching from DriverManager to DataSource is a best practice in modern Java applications because it supports connection pooling, is more configurable, and decouples your code from the specific database driver implementation.

While DriverManager creates a physical connection every time you call getConnection(), a DataSource (specifically a pooling one) maintains a set of open connections that can be reused, significantly improving performance.

1. The DriverManager Approach (Old way)

You are likely used to this pattern:

// Hardcoded driver details and physical connection creation
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/db", "user", "pass");

2. The DataSource Approach (Modern way)

With DataSource, you configure the object once and then use it to get connections throughout your application.

Using Apache Commons DBCP (Connection Pooling)

To use a DataSource with pooling, you can use a library like Apache Commons DBCP’s BasicDataSource.

package org.kodejava.jdbc;

import org.apache.commons.dbcp2.BasicDataSource;
import javax.sql.DataSource;

public class DatabaseConfig {
    private static final BasicDataSource dataSource;

    static {
        dataSource = new BasicDataSource();
        dataSource.setUrl("jdbc:mysql://localhost/musicdb");
        dataSource.setUsername("music");
        dataSource.setPassword("s3cr*t");

        // Optional: Configure pooling parameters
        dataSource.setInitialSize(5);
        dataSource.setMaxTotal(10);
    }

    public static DataSource getDataSource() {
        return dataSource;
    }
}

3. Using the Connection in your Code

Once you have the DataSource instance, getting a connection is consistent regardless of the underlying implementation:

public void fetchData() {
    DataSource ds = DatabaseConfig.getDataSource();

    // The try-with-resources ensures the connection is "closed" 
    // (returned to the pool) automatically.
    try (Connection conn = ds.getConnection()) {
        // Use the connection as usual
        var stmt = conn.prepareStatement("SELECT * FROM record");
        var rs = stmt.executeQuery();
        // ... process results
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

Why use DataSource?

  • Connection Pooling: Reusing connections is much faster than opening/closing them for every request.
  • Decoupling: Your business logic only knows about the javax.sql.DataSource interface. You can switch from BasicDataSource to HikariCP (another popular pool) without changing your data-access code.
  • JNDI Support: In Jakarta EE environments, you can look up a DataSource configured in the application server via JNDI, keeping credentials out of your source code.
  • Spring Integration: If you use Spring Framework, JdbcTemplate is designed to work directly with a DataSource.

Maven Dependency

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>2.13.0</version>
</dependency>

How do I use JNDI to get database connection or data source?

package org.kodejava.jndi;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.Servlet;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

@WebServlet(name = "JNDITestServlet", urlPatterns = "/jndi-datasource-test")
public class JNDITestServlet extends HttpServlet implements Servlet {

    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response) throws IOException {

        // This implementation of doGet method show us an example to use
        // conn obtained in the getConnection() method.
        DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");

        response.setContentType("text/html");
        PrintWriter writer = response.getWriter();

        try (Connection connection = getConnection()) {
            // A query to get current date time from Oracle database
            String sql = "select current_timestamp() as SYSDATE";
            PreparedStatement statement = connection.prepareStatement(sql);
            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                Date date = rs.getTimestamp("SYSDATE");
                writer.println("The current date is " + format.format(date));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * Get a database connection from the registered data source in the
     * servlet container. To registered the JNDI data source you should
     * refer to your servlet container documentation.
     *
     * @return a database connection
     */
    private Connection getConnection() {
        Connection connection = null;
        try {
            InitialContext initialContext = new InitialContext();
            Context context = (Context) initialContext.lookup("java:/comp/env");
            DataSource dataSource = (DataSource) context.lookup("jdbc/DataSource");
            connection = dataSource.getConnection();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;
    }
}

Configure the JNDI DataSource in Tomcat conf/context.xml configuration file. And don’t forget to copy the JDBC driver library to Tomcat’s lib directory.

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    ...
    <Resource name="jdbc/DataSource" auth="Container" type="javax.sql.DataSource"
               maxTotal="100" maxIdle="30" maxWaitMillis="10000"
               username="root" password="" driverClassName="com.mysql.cj.jdbc.Driver"
               url="jdbc:mysql://localhost:3306/kodejava"/>
    ...
</Context>

Maven dependencies

<dependencies>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
    </dependency>
</dependencies>

Maven Central