Connexion Java JDBC
Ouvrez et gérez les connexions à une base de données en Java avec l'interface Connection — ouverture, fermeture et configuration.
Une Connection est une session active avec la base de données. C'est l'objet que vous récupérez depuis DriverManager (ou un DataSource), et c'est la fabrique de tout le reste — instructions, transactions, points de sauvegarde, métadonnées. Une connexion est également une ressource rare et coûteuse : chaque connexion ouverte monopolise un socket et une session côté serveur, d'où la règle fondamentale : ouvrir tard, fermer rapidement.
Ce chapitre explique comment construire une URL de connexion, les trois façons d'ouvrir une Connection, pourquoi try-with-resources est incontournable, les paramètres de session que vous pouvez régler, et les erreurs que vous rencontrerez en cas de mauvaise configuration. Il suppose que vous avez déjà chargé un pilote — consultez les pilotes JDBC et l'introduction JDBC pour une vue d'ensemble.
L'URL de connexion
Tout ce dont DriverManager a besoin pour trouver et atteindre une base de données est encodé dans l'URL :
jdbc:<subprotocol>://<host>:<port>/<database>?<key=value&...>Par exemple jdbc:postgresql://db.internal:5432/shop?ssl=true. Le préfixe jdbc: est obligatoire ; le sous-protocole sélectionne le pilote ; le reste est spécifique au fournisseur, mais conventionnellement host, port, base de données et une chaîne de requête d'options. Quelques URL réelles à reconnaître :
| Base de données | Exemple d'URL |
|---|---|
| PostgreSQL | jdbc:postgresql://localhost:5432/shop |
| MySQL | jdbc:mysql://localhost:3306/shop?useSSL=true |
| H2 (en mémoire) | jdbc:h2:mem:testdb |
| SQLite (fichier) | jdbc:sqlite:/data/shop.db |
Le sous-protocole (postgresql, mysql, h2, sqlite) permet à DriverManager de décider quel pilote enregistré doit gérer l'URL, donc le saisir correctement indique à JDBC quelle base de données vous visez.
Trois façons de l'ouvrir
// 1. URL with credentials as arguments
Connection a = DriverManager.getConnection(url, "app", "secret");
// 2. URL with a Properties bag (user, password, plus driver-specific keys)
Properties props = new Properties();
props.setProperty("user", "app");
props.setProperty("password", "secret");
props.setProperty("connectTimeout", "10");
Connection b = DriverManager.getConnection(url, props);
// 3. From a pooled DataSource (preferred for applications)
Connection c = dataSource.getConnection();DriverManager vs. DataSource
DriverManager.getConnection(...) ouvre une connexion physique toute neuve à chaque appel, puis la détruit à la fermeture. Cette négociation — résolution DNS, TCP, TLS, authentification — coûte des dizaines de millisecondes, ce qui convient à un script mais est ruineux pour un serveur traitant de nombreuses requêtes.
Un DataSource adossé à un pool de connexions (HikariCP, Apache DBCP, ou celui fourni par votre serveur d'applications) maintient un ensemble de connexions physiques ouvertes et les distribue à la demande. Appeler getConnection() en emprunte une ; appeler close() la remet dans le pool au lieu de vraiment la fermer. Pour toute application longue durée, préférez un DataSource avec pool ; n'utilisez DriverManager que dans de petits outils, des tests et des exemples.
Toujours la fermer — utilisez try-with-resources
Connection, Statement et ResultSet implémentent tous AutoCloseable. Les déclarer dans un en-tête try-with-resources garantit leur fermeture dans l'ordre inverse, même en cas d'exception — c'est l'habitude la plus importante en JDBC :
try (Connection conn = DriverManager.getConnection(url, "app", "secret")) {
// use conn...
} // conn.close() runs here automatically, even on exceptionLaisser fuir des connexions (oublier de les fermer) épuise le pool et finit par bloquer toute l'application — une panne de production classique. Notez qu'ouvrir une Connection lève une SQLException vérifiée, donc l'appel se trouve toujours dans un try (ou dans une méthode qui déclare throws SQLException).
Une fois la connexion obtenue, vous l'utilisez pour créer des Statements et des PreparedStatements — qui doivent figurer dans le même en-tête try-with-resources pour se fermer avant la connexion :
try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement("SELECT name FROM users WHERE id = ?")) {
ps.setInt(1, 42);
// ...read the ResultSet...
} // ps closes first, then conn — reverse declaration orderConfigurer une connexion
Une fois ouverte, une connexion porte des paramètres au niveau de la session :
| Méthode | Ce qu'elle fait |
|---|---|
setAutoCommit(false) | Démarre une transaction manuelle ; vous appelez ensuite commit() ou rollback() vous-même. Voir Transactions JDBC. |
setTransactionIsolation(...) | Choisit un niveau d'isolation (p. ex. TRANSACTION_READ_COMMITTED). |
setReadOnly(true) | Indique que la connexion n'effectue aucune écriture ; certains pilotes l'optimisent. |
setSchema(...) / setCatalog(...) | Sélectionne l'espace de noms contre lequel les requêtes s'exécutent. |
isValid(timeout) | Retourne true si la connexion est toujours active ; les pools l'utilisent pour écarter les connexions mortes. |
Ces paramètres sont par session, ils se réinitialisent donc quand une vraie connexion se ferme — mais avec un pool, une connexion empruntée peut encore porter les paramètres laissés par un utilisateur précédent. C'est pourquoi les pools réinitialisent autoCommit et l'isolation au retour, et pourquoi vous devez définir ce dont vous avez besoin plutôt que de supposer des valeurs par défaut.
Erreurs de connexion courantes
Lorsqu'une connexion échoue, vous obtenez presque toujours une SQLException ; le message vous indique quelle couche a rompu :
No suitable driver found for ...— la classe du pilote n'a jamais été chargée, ou le sous-protocole de l'URL est mal orthographié, donc aucun pilote enregistré ne le revendique. Corrigez la dépendance ou l'URL (voir Pilotes JDBC).Connection refused— rien n'écoute sur cet hôte/port : la base de données est arrêtée, ou l'hôte/port dans l'URL est incorrect.- Authentification /
password authentication failed— mauvaisuseroupassword, ou l'utilisateur n'a pas les droits sur cette base de données. - Délai de connexion dépassé — l'hôte est inaccessible (pare-feu, mauvais réseau). Définissez
connectTimeoutpour que l'appel échoue rapidement au lieu de rester bloqué.
Un exemple complet : anatomie d'une URL de connexion
Ce programme décompose une URL JDBC réaliste en ses composants et construit le conteneur Properties que vous passeriez avec elle — les deux entrées dont getConnection a besoin — sans nécessiter de base de données active.
Ce que l'on retient de l'exécution :
- L'URL n'est pas opaque — c'est une donnée structurée.
getConnectionanalyse exactement ces éléments : le sous-protocole choisit le pilote, et l'hôte/port/base de données indiquent à ce pilote où se connecter. Lire une URL à voix haute est le moyen le plus rapide de déboguer les erreurs de « mauvaise base de données ». - La chaîne de requête (
?ssl=true&applicationName=reports) contient des options spécifiques au pilote. Les mêmes paramètres peuvent figurer dans l'URL ou dans le conteneurProperties— les deux atteignent le pilote, et vous les mélangez selon votre goût. - Les informations d'identification appartiennent à
Properties(ou à la configuration duDataSource), pas codées en dur dans la chaîne d'URL que vous journalisez. L'exemple masque le mot de passe à la sortie pour exactement cette raison — ne journalisez jamais les informations d'identification. connectTimeoutest une vraie propriété du pilote PostgreSQL. Le réglage réside dans ces paires clé/valeur, c'est pourquoi vous sous-classez rarement quoi que ce soit : la configuration, et non le code, forme une connexion.- Cela s'est exécuté sans base de données car la construction des entrées de
getConnectionest un travail purement sur les chaînes. La partie coûteuse — le socket et la session serveur — ne se produit qu'à l'appelgetConnectionlui-même, c'est pourquoi vous le différez et le fermez rapidement.