Apache Commons DBCP (Database Connection Pool) est l'une des solutions de gestion de pools de connexions les plus éprouvées de l'écosystème Apache. Bien que la version originale ait cessé d'évoluer il y a plusieurs années, le projet DBCP2 assure la continuité avec des performances accrues et un support pour les versions récentes du JDK et de JDBC.
1. Intégration des dépendances Maven
Pour utiliser DBCP2 dans un projet Java, vous devez ajouter la bibliothèque principale ainsi que le pilote JDBC correspondant à votre base de données (par exemple, MySQL) dans votre fichier pom.xml :
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
2. Définition des paramètres de connexion
La configuration est généralement centralisée dans un fichier .properties. Voici un exemple nommé datasource.properties illustrant les réglages de base et les paramètres d'optimisation du pool :
# Informations de base sur le pilote et la base
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/db_application
username=dev_user
password=secure_password
# Paramètres de gestion du pool
# Taille initiale du pool au démarrage
initialSize=5
# Nombre maximal de connexions actives simultanément
maxTotal=30
# Nombre maximal de connexions inactives conservées
maxIdle=15
# Nombre minimal de connexions inactives conservées
minIdle=2
# Temps d'attente maximum (ms) pour obtenir une connexion avant erreur
maxWaitMillis=45000
# Options JDBC additionnelles
connectionProperties=useUnicode=true;characterEncoding=UTF-8;serverTimezone=Europe/Paris
defaultAutoCommit=true
defaultTransactionIsolation=READ_COMMITTED
3. Initialisation du DataSource via Factory
La classe BasicDataSourceFactory permet de transformer facilement un objet de propriétés en une source de données expliotable par l'application.
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.dbcp2.BasicDataSourceFactory;
import java.io.InputStream;
import java.util.Properties;
public class DatabaseConnector {
private static BasicDataSource dataSource;
static {
try (InputStream input = DatabaseConnector.class.getClassLoader().getResourceAsStream("datasource.properties")) {
Properties config = new Properties();
if (input == null) {
throw new RuntimeException("Fichier de configuration introuvable.");
}
config.load(input);
dataSource = BasicDataSourceFactory.createDataSource(config);
} catch (Exception e) {
e.printStackTrace();
}
}
public static BasicDataSource getDataSource() {
return dataSource;
}
}
4. Exemples d'implémentation
DBCP2 offre plusieurs manières d'interagir avec le pool. Voici les approches les plus courantes.
Utilisation directe avec BasicDataSource
C'est l'appproche la plus simple, où l'on récupère une connexion pour exécuter une requête SQL standard.
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class SimpleQueryExecutor {
public void executeTask() {
String sql = "SELECT id, name FROM users WHERE active = 1";
try (Connection conn = DatabaseConnector.getDataSource().getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
System.out.println("ID: " + rs.getInt("id") + " - Nom: " + rs.getString("name"));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Configuraton manuelle du pool d'objets
Dans des scénarios plus complexes, il est possible d'assembler manuellement les composants du pool (ConnectionFactory et PoolableConnection).
import org.apache.commons.dbcp2.*;
import org.apache.commons.pool2.impl.GenericObjectPool;
import javax.sql.DataSource;
public class ManualPoolBuilder {
public static DataSource buildCustomDataSource(String uri) {
// Création de la fabrique de connexions natives
ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(uri, null);
// Liaison avec le mécanisme de mise en pool de DBCP
PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, null);
// Configuration du pool d'objets générique
GenericObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(poolableConnectionFactory);
poolableConnectionFactory.setPool(connectionPool);
// Export en tant que DataSource standard
return new PoolingDataSource<>(connectionPool);
}
}
Enregistrement d'un PoolingDriver
Cette méthode permet d'enregistrer le pool directement auprès du DriverManager de JDBC, rendant le pool accessible via une URL spécifique.
import org.apache.commons.dbcp2.PoolingDriver;
import org.apache.commons.pool2.ObjectPool;
import java.sql.DriverManager;
public class DriverRegistry {
public void setupDriver(ObjectPool<PoolableConnection> pool) throws Exception {
Class.forName("org.apache.commons.dbcp2.PoolingDriver");
PoolingDriver driver = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:");
// Enregistrement du pool sous un nom unique
driver.registerPool("app_pool", pool);
}
public void displayStats() throws Exception {
PoolingDriver driver = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:");
ObjectPool<?> pool = driver.getConnectionPool("app_pool");
System.out.println("Actives: " + pool.getNumActive());
System.out.println("Inactives: " + pool.getNumIdle());
}
}