Cos'è JDBC? Introduzione alla connettività del database Java

JDBC (Java Database Connectivity) è l'API Java che gestisce la connessione a un database, l'emissione di query e comandi e la gestione dei set di risultati ottenuti dal database. Rilasciato come parte di JDK 1.1 nel 1997, JDBC è stato uno dei primi componenti sviluppati per il livello di persistenza Java.

JDBC è stato inizialmente concepito come un'API lato client, consentendo a un client Java di interagire con un'origine dati. La situazione è cambiata con JDCB 2.0, che includeva un pacchetto opzionale che supportava le connessioni JDBC lato server. Ogni nuova versione di JDBC da allora ha caratterizzato gli aggiornamenti sia per il pacchetto lato client ( java.sql) che per il pacchetto lato server ( javax.sql). JDBC 4.3, la versione più recente al momento della stesura di questo documento, è stata rilasciata come parte di Java SE 9 a settembre 2017.

Questo articolo presenta una panoramica di JDBC, seguita da un'introduzione pratica all'uso dell'API JDBC per connettere un client Java con SQLite, un database relazionale leggero.

Come funziona JDBC

Sviluppato come alternativa all'API ODBC (Open Database Connectivity) basata su C, JDBC offre un'interfaccia a livello di programmazione che gestisce i meccanismi delle applicazioni Java che comunicano con un database o RDBMS. L'interfaccia JDBC è composta da due livelli:

  1. L'API JDBC supporta la comunicazione tra l'applicazione Java e il gestore JDBC.
  2. Il driver JDBC supporta la comunicazione tra il gestore JDBC e il driver del database.

JDBC è l'API comune con cui interagisce il codice dell'applicazione. Al di sotto c'è il driver conforme a JDBC per il database che stai utilizzando.

La Figura 1 è una panoramica dell'architettura di JDBC nel livello di persistenza Java.

JavaWorld /

Utilizzo di JDBC per connettersi a un database

Uno dei fatti fortunati della programmazione nell'ecosistema Java è che probabilmente troverai un connettore di database JDBC stabile per qualsiasi database tu scelga. In questo tutorial useremo SQLite per conoscere JDBC, principalmente perché è così facile da usare.

I passaggi per la connessione a un database con JDBC sono i seguenti:

  1. Installa o individua il database a cui desideri accedere.
  2. Includere la libreria JDBC.
  3. Assicurati che il driver JDBC di cui hai bisogno sia sul tuo classpath.
  4. Utilizzare la libreria JDBC per ottenere una connessione al database.
  5. Usa la connessione per emettere comandi SQL.
  6. Chiudi la connessione quando hai finito.

Eseguiremo questi passaggi insieme.

Trovare un driver JDBC

Per trovare un driver per il database che desideri utilizzare, fai semplicemente una ricerca sul web per il tuo database e JDBC. Ad esempio, digitando " mysql jdbc driver" verrà visualizzato un driver per MySQL. Ti sfido a trovare un database compatibile con Java senza un driver JDBC!

Passaggio 1. Scarica e installa SQLite

SQLite è un database molto compatto. Non è destinato all'uso in produzione, ma è un'ottima scelta per provare rapidamente le cose. SQLite utilizza un file come database funzionale, senza richiedere l'installazione di alcun servizio o demone.

Per iniziare con questa demo, vai avanti e scarica il database di esempio SQLite. Decomprimere il .dbfile e salvarlo in un luogo che non dimenticherai.

Questo file contiene sia un database funzionale basato su file che uno schema di esempio e dati che possiamo utilizzare.

SQL e JDBC

NoSQL è diventato popolare negli ultimi dieci anni, ma i database relazionali rimangono il tipo più comune di datastore in uso. Un database relazionale è un repository strutturato costituito da tabelle con colonne e righe. SQL (Structured Query Language) è il linguaggio utilizzato dagli architetti dei dati per eseguire operazioni come creare, leggere, aggiornare ed eliminare nuovi record in un database relazionale. JDBC è un livello adattatore da Java a SQL: fornisce agli sviluppatori Java un'interfaccia comune per la connessione a un database, l'emissione di query e comandi e la gestione delle risposte.

Passaggio 2. Importare JDBC nell'applicazione Java

Potremmo eseguire la codifica in un IDE, ma la codifica direttamente in un editor di testo dimostrerà meglio la semplicità di JDBC. Per iniziare, dovrai disporre di un'installazione JDK compatibile per il tuo sistema operativo.

Supponendo che tu abbia installato gli strumenti di sviluppo della piattaforma Java, possiamo iniziare creando un semplice programma Java. Nel tuo editor di testo, incolla il codice mostrato nel Listato 1. Chiama questo file WhatIsJdbc.java.

Listato 1. Un semplice programma Java

 class WhatIsJdbc{ public static void main(String args[]){ System.out.println("Hello JavaWorld"); } } 

Ora compilare il codice inserendo il comando: javac WhatIsJdbc.java. La compilazione produrrà il WhatIsJdbc.classfile. Eseguire questo file dalla riga di comando con la chiamata: java WhatIsJdbc.

[Vedere "Cos'è il JDK? Introduzione al Java Developer Kit" per ulteriori informazioni sull'interazione con JDK sulla riga di comando.]

Una volta che hai un programma Java di base, puoi includere le librerie JDBC. Incolla il codice dal Listato 2 all'inizio del tuo semplice programma Java.

Listato 2. Importazioni JDBC

 import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.ResultSet; import java.sql.Statement; 

Ciascuna di queste importazioni fornisce l'accesso a una classe che facilita la connessione al database Java standard:

  • Connection rappresenta la connessione al database.
  • DriverManagerottiene la connessione al database. (Un'altra opzione è DataSource, usata per il pool di connessioni.)
  • SQLException gestisce gli errori SQL tra l'applicazione Java e il database.
  • ResultSete Statementmodellare i set di risultati dei dati e le istruzioni SQL.

A breve vedremo ciascuno di questi in azione.

Passaggio 3. Aggiungere il driver JDBC al classpath

Successivamente, aggiungerai il driver SQLite al tuo classpath. Un driver JDBC è una classe che implementa l'API JDBC per un database specifico.

Scarica il driver SQLite da GitHub. Assicurati di ottenere il .jarfile più recente e di archiviarlo in un luogo che ricorderai.

The next time you execute your Java program, you will pull that .jar file in via the classpath. There are several ways to set the classpath. Listing 3 shows how to do it using a command-line switch.

Listing 3. Executing SQLite driver on the Java classpath

 java.exe -classpath /path-to-driver/sqlite-jdbc-3.23.1.jar:. WhatIsJdbc 

Notice that we've set the classpath to point at the driver and the local directory; this way Java will still find our class file.

Step 4. Obtain a database connection

The classpath now has access to the driver. Now, change your simple Java application file to look like the program in Listing 4.

Listing 4. Using the JDBC Connection class to connect to SQLite

 import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.ResultSet; import java.sql.Statement; class WhatIsJdbc{ public static void main(String[] args) { Connection conn = null; try { String url = "jdbc:sqlite:path-to-db/chinook/chinook.db"; conn = DriverManager.getConnection(url); System.out.println("Got it!"); } catch (SQLException e) { throw new Error("Problem", e); } finally { try { if (conn != null) { conn.close(); } } catch (SQLException ex) { System.out.println(ex.getMessage()); } } } } 

Compile and execute this code. Assuming all goes well, you will get an affirming message.

No suitable driver found?

If you've received an error that looks like "No suitable driver found for jdbc:sqlite," then you need to revisit the classpath and make sure it points to the driver you downloaded. Failed driver connection is the most common stumbling block for beginners using JDBC. Don't sweat it; just fix it.

Now we're ready for some SQL commands.

Step 5. Query the database

With the live connection object in hand, we can do something useful, like querying the database. Listing 5 shows how to query SQLite using the JDBC Connection and Statement objects.

Listing 5. Querying the database with JDBC

 import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.ResultSet; import java.sql.Statement; class WhatIsJdbc{ public static void main(String[] args) { Connection conn = null; try { String url = "jdbc:sqlite:path-to-db-file/chinook/chinook.db"; conn = DriverManager.getConnection(url); Statement stmt = null; String query = "select * from albums"; try { stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(query); while (rs.next()) { String name = rs.getString("title"); System.out.println(name); } } catch (SQLException e ) { throw new Error("Problem", e); } finally { if (stmt != null) { stmt.close(); } } } catch (SQLException e) { throw new Error("Problem", e); } finally { try { if (conn != null) { conn.close(); } } catch (SQLException ex) { System.out.println(ex.getMessage()); } } } } 

In Listing 5 we use our Connection object to obtain a Statement object: conn.createStatement(). We then use this object to execute an SQL query: stmt.executeQuery(query).

The executeQuery command returns a ResultSet object, which we then use to iterate over the data with while (rs.next()). In this example, you should see the album titles we've queried on as output.

Notice that we also closed the connection, via a call to conn.close().

Network connections with JDBC

The database connection string in Listing 5 is for a local connection: jdbc:sqlite:path-to-db-file/chinook/chinook.db. To access the database via a network, the connection string would need to include the network URL and (usually) credentials for accessing it.

Doing more with JDBC

So far we've covered the basics of using JDBC to connect to a database and issue SQL commands. While Statementss and ResultSets work well for common scenarios, you'll likely need additional options for larger or more complex applications. Fortunately, the JDBC library continues evolving to meet most database access needs.

PreparedStatements

One easy way to increase the flexibility of your code is to replace the Statement class with PreparedStatement, as shown in Listing 6.

Listing 6. Using JDBC PreparedStatements

 String prepState = "insert into albums values (?, ?);"; PreparedStatement prepState = connection.prepareStatement(sql); prepState.setString(1, "Uprising"); prepState.setString(2, "Bob Marley and the Wailers "); int rowsAffected = preparedStatement.executeUpdate(); 

PreparedStatement replaces Statement's hard-coded values with question marks (?). Using PreparedStatements optimizes your code for reuse: a PreparedStatement is compiled only once, and can then be reused with a variety of parameters. As your code base grows, you simply insert new values into the statement, instead of hacking the string object itself.

Batch updates

Whenever an application has several updates to issue, doing them in batches can greatly benefit performance. The essence of batching is to take the multiple updates and collect them together, then issue them all at once. Listing 7 uses JDBC's batch methods to perform a batch update of several PreparedStatements.

Listing 7. Batching with PreparedStatement

 prepState.setString(1, "Uprising"); prepState.setString(2, "Bob Marley and the Wailers"); preparedStatement.addBatch(); prepState.setString(1, "Wildflowers"); prepState.setString(2, "Tom Petty and the Heartbreakers"); preparedStatement.addBatch(); int[] rowsAffected = preparedStatement.executeBatch(); 

JDBC transactions

Transactions in relational databases allow for a set of updates to be wrapped in an interaction that either succeeds or fails altogether. The basics of using a transaction via JDBC are to tell the system to turn off auto-commit, and then manually tell the system to commit when you are done. By default, auto-commit is on, which means whenever an executeUpdate or executeInsert is run, the command is committed.

Listing 8 shows a small slice of a JDBC transaction.

Listing 8. JDBC transactions

 connection.setAutoCommit(false); // Use executeUpdate multiple times connection.commit(); 

When connection.commit() is encountered, all the updates wrapped inside will be attempted, and if any fail, they all will be rolled back.

There are many more features in JDBC 4.3 worth exploring, including using CallableStatement for stored procedures, using DataSource objects for improved application performance (especially via connection pooling), and converting a JDBC ResultSet to a Java Stream.

Database-specific features

Although every JDBC-compliant database offers the same core features for connecting and interacting with a database via SQL, some databases do more than others. As an example, Oracle DB offers result caching, which is not required by the JDBC specification. Here's an example:

 conn.prepareStatement ("select /*+ result_cache */ * from employees where employee_id < : 1"); 

This example is taken from the documentation for Oracle's JDBC OCI Driver.

Conclusion

JDBC is one of Java's oldest APIs, providing an easy-to-use solution for one of the perennial needs of Java application development. Knowing just the few JDBC calls demonstrated in this article will get you started using JDBC to connect to virtually any database. Once you've got those commands down, you can begin to explore some of the more sophisticated options that have been built into JDBC.

Sebbene JDBC sia sufficiente per applicazioni più semplici, la maggior parte degli sviluppatori alla fine guarderà alla Java Persistence API (JPA) per sviluppare un livello di accesso ai dati più formale. JPA richiede un lavoro più iniziale e una comprensione più sofisticata dell'architettura dell'applicazione, ma offre un livello di accesso ai dati più coerente, isolato e ben definito. Per ulteriori informazioni sullo sviluppo del livello di persistenza dei dati per le applicazioni Java, vedere il compagno di questo articolo, "Che cos'è JPA? Introduzione all'API Java Persistence".

Questa storia, "Che cos'è JDBC? Introduzione alla connettività del database Java" è stata originariamente pubblicata da JavaWorld.