W3docs

Driver JDBC in Java

Tipi di driver JDBC, caricamento in Java moderno e uso di DriverManager e DataSource per ottenere connessioni al database.

Un driver JDBC è la libreria fornita dal vendor che trasforma le chiamate generiche java.sql nel protocollo di rete specifico compreso dal database. L'API JDBC fa parte del JDK; il driver è un JAR esterno da aggiungere al classpath. Senza driver, nessuna connessione.

Questo capitolo tratta i quattro tipi di driver (e perché oggi ne conta solo uno), come Java moderno carica automaticamente i driver senza Class.forName, la differenza tra DriverManager e DataSource, e come DriverManager decide quale driver gestisce un dato URL. Per una visione d'insieme di come l'API JDBC si integra nel sistema, vedi Java JDBC Introduction; per agire su una connessione attiva una volta ottenuta, vedi Java JDBC Connection.

I quattro tipi di driver

La specifica JDBC definisce quattro tipi storici di driver. Nella pratica moderna si usa quasi sempre il Tipo 4:

TipoNomeNote
1Bridge JDBC-ODBCObsoleto; rimosso dal JDK in Java 8
2Native-APIRacchiude una libreria client C; richiede codice nativo installato
3Network protocolComunica con un middleware che parla con il database
4Pure-Java (thin)Un singolo JAR, tutto Java, parla direttamente il protocollo wire del DB

I driver di Tipo 4 — org.postgresql.Driver, com.mysql.cj.jdbc.Driver, il driver H2 — sono semplicemente un JAR nel classpath. È quello che aggiungi a pom.xml o build.gradle. Poiché sono puro Java, girano su qualsiasi piattaforma supportata dalla JVM, senza nulla da installare sulla macchina host. Tratta i tipi più vecchi come storici: li vedrai in vecchia documentazione e domande d'esame, ma non li userai nel codice nuovo.

Caricare un driver: di solito non fai nulla

I vecchi tutorial mostrano Class.forName("com.mysql.cj.jdbc.Driver"). Da JDBC 4.0 (Java 6) quella riga è inutile. I driver includono un file META-INF/services/java.sql.Driver e DriverManager li registra automaticamente tramite il meccanismo ServiceLoader la prima volta che chiami getConnection. Il codice moderno è quindi semplicemente:

// No Class.forName needed — the driver JAR self-registers.
Connection conn = DriverManager.getConnection(
    "jdbc:postgresql://localhost:5432/shop", "app", "secret");

DriverManager vs. DataSource

Due modi per ottenere una connessione:

  • DriverManager.getConnection(url, user, password) — il più semplice; adatto per strumenti, script e demo. Apre una connessione fisica nuova a ogni chiamata.
  • DataSource — l'approccio preferito per applicazioni e server. Un DataSource (di solito supportato da un connection pool come HikariCP) fornisce connessioni in pool, quindi close() restituisce la connessione al pool invece di chiudere un socket.
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl("jdbc:postgresql://localhost:5432/shop");
ds.setUsername("app");
ds.setPassword("secret");
try (Connection conn = ds.getConnection()) { /* borrowed from the pool */ }

L'URL JDBC

Ogni connessione inizia con un URL JDBC, che ha sempre la forma jdbc:<subprotocol>:<subname>:

jdbc:postgresql://localhost:5432/shop
│    │           │
│    │           └─ subname: host, port, database, options
│    └───────────── subprotocol: identifies the vendor/driver
└────────────────── scheme: always "jdbc"

Il subprotocol (postgresql, mysql, h2, oracle, sqlserver) è la parte che decide quale driver gestisce la richiesta. Ogni vendor documenta il proprio formato URL e le opzioni che seguono il nome del database (impostazioni TLS, fuso orario, flag di connessione), quindi controlla la documentazione del driver per la sintassi esatta.

Come DriverManager sceglie un driver

Quando chiami getConnection, DriverManager scorre la sua lista di driver registrati e chiede a ciascuno "riconosci questo URL?" tramite Driver.acceptsURL. Il primo che risponde sì viene usato; se nessuno lo fa, si ottiene No suitable driver found. Un driver risponde tipicamente "sì" solo quando il subprotocol dell'URL corrisponde al proprio — ecco perché è il subprotocol, non l'host, a instradare la richiesta.

Un esempio pratico: ispezione del registro dei driver

Questo programma elenca i driver che DriverManager conosce, poi gli chiede di connettersi a tre URL di vendor diversi — permettendoti di osservare in azione il contratto di corrispondenza URL.

java— editable, runs on the server

Cosa ricavare dall'esecuzione:

  • DriverManager.getDrivers() restituisce i driver registrati come Enumeration. Su un runtime senza JAR driver la lista è vuota — aggiungere postgresql.jar al classpath farebbe comparire automaticamente il Driver PostgreSQL, senza alcuna chiamata a Class.forName.
  • Il subprotocol dell'URL (la parte dopo jdbc:postgresql, mysql, h2) è ciò su cui ogni driver effettua la corrispondenza. È così che una chiamata getConnection viene instradata al vendor giusto: il driver rivendica il proprio subprotocol.
  • Ogni URL ha fallito allo stesso modo qui perché non è presente alcun driver. In un deployment reale, esattamente un driver rivendicherebbe ciascun URL; se dimentichi la dipendenza vedi esattamente questo messaggio "No suitable driver found" — un sintomo di JAR mancante, non di password errata.
  • La registrazione è automatica tramite ServiceLoader, ma il JAR del driver deve comunque essere nel classpath. La lezione: un errore "No suitable driver" è un problema di build/dipendenza, da correggere in pom.xml, non nel codice Java.
  • Driver espone getMajorVersion/getMinorVersion, quindi puoi registrare esattamente quale versione del driver è in esecuzione — utile quando un bug dipende dalla versione del driver, non dal tuo codice.

Una volta che un driver è nel classpath e getConnection restituisce una Connection attiva, il passo successivo è eseguire SQL attraverso di essa — vedi Java JDBC Connection e Java JDBC Statement.

Esercitazione

Pratica
Un collega ha un'applicazione moderna (Java 17) che genera 'No suitable driver found for jdbc:postgresql://...' all'avvio. Qual è la correzione più probabile?
Un collega ha un'applicazione moderna (Java 17) che genera 'No suitable driver found for jdbc:postgresql://...' all'avvio. Qual è la correzione più probabile?
Was this page helpful?