Java e database: introduzione a JDBC

Java possiede ormai da tempo JDBC, uno strato di astrazione specifico per i database relazionali, in questo articolo verrà fatta una panoramica su cos’è JDBC e come si usi.

Java è un linguaggio che fa del multipiattaforma la sua arma principale. Infatti ultimamente c’è stato il suo massiccio utilizzo anche nelle tecnologie embedded come cellulari (J2ME) e sim (JavaCard). Per rendere onore a questa filosofia del multipiattaforma, dell’astrazione dal singolo sistema operativo, i progettisti della Sun non potevano che progettare una libreria di accesso ai database coerente.

JDBC è un API Java che fornisce uno strato di accesso verso i database completo e soprattutto ad oggetti, c’è indipendenza dal tipo di database e l’accesso viene generalizzato a livello di applicazione.

Progettando un’applicazione Java che utilizzi JDBC ci troviamo davanti a due successivi «strati»: DriverLayer ApplicationLayer. Il DriverLayer è lo strato di JDBC che si occupa dell’interfacciamento con il database mentre l’ApplicationLayer riguarda le funzionalità che JDBC offre per manipolare dati tramite costrutti Java.

JDBC

JDBC

Il DriverLayer è essenzialmente composto dall’interfaccia Driver e dalla classe DriverManager. Il Driver è il vero e proprio driver che ci permette il collegamento al database e che richiamiamo nel nostro programma, mentre il DriverManager gestisce l’instaurazione della connessione con il database e la restituzione della connessione al nostro programma, anche se in molti casi è più conveniente crearsi da soli un proprio DriverManager per particolari esigenze, come ad esempio pooling di connessioni.

L’ApplicationLayer , che riguarda appunto più il lato applicativo, è principalmente composto dalle interfacce Connection, Statement, ResultSet, PreparedStatement ed SQLException. Connection è quella che modella la connessione al database e serve per creare gli Statement o i PreparedStatement che sono i costrutti che ci permettono di eseguire interrogazioni, modifiche e inserimenti verso il database.

I PreparedStatement sono praticamente degli Statement quasi completi ai quali dobbiamo passare dei parametri, anche a run-time, e quindi migliorano l’efficienza specialmente in programmi ripetitivi. L’oggetto che modella i dati che il database ci restituisce in prima istanza dopo una query è il ResultSet, mentre l’SQLException è una semplice classe che estende Exception e che tramite opportuni metodi ci permette di venire a conoscenza degli errori generati dalla nostra applicazione riguardanti JDBC.

Prima di immergerci in qualche riga di codice dobbiamo parlare dei driver che permettono il collegamento al database. In un primo momento infatti un ingenuo programmatore non riesce bene a capire le sottili differenze dei driver che si trova davanti quando vuole collegare la sua applicazione ad un database. Invece le differenze ci sono e sono importanti. Bisogna prima di tutto dire che esistono 4 diversi tipi di driver JDBC:

  1. JDBC-ODBC
  2. JAVA e API del DB
  3. Driver di rete in JAVA
  4. Driver nativo in JAVA

Il primo è un driver che usa un driver ODBC e converte le chiamate JAVA per questo driver. Non è indipendente dalla piattaforma e solitamente ha delle prestazioni scadenti. La seconda soluzione sfrutta una libreria del DB e quindi traduce sempre le chiamate JAVA, però ha una prestazione migliore del primo pur non essendo indipendente dalla piattaforma.

Il driver di rete è un ottima soluzione visto che sfrutta un server intermedio tra applicazione e DB, avendo quindi un driver molto leggero. Questo chiaramente però conviene solo nel caso che la rete non sia congestionata o che si tratti di una LAN. Infine c’è il driver nativo in JAVA, che comunica direttamente col database, indipendente dalla piattaforma e con buone prestazioni. Chiaramente i migliori sono quelli del terzo e quarto tipo (anche se non sempre sono disponibili) , dipendenti anche dalla natura dell’applicazione che deve essere sviluppata.

Una volta che abbiamo l’SDK Java, il database e il driver per la connessione ad esso possiamo ad iniziare a collegarci ad esso. Per il caricamento del driver e la connessione abbiamo bisogno della classe DriverManager. Per caricare il driver usiamo Class.forName al quale passiamo il nome del driver. Ad esempio il caricamento del driver per Oracle 9i Lite è il seguente:

Questo metodo sfrutta il blocco di inizializzazione statica del Driver. Successivamente il DriverManager ci restituisce una connessione al database, incapsulandola nell’oggetto Connection , tramite il suo metodogetConnection al quale devo passare come argomento un URI (Uniform Resource Identificator), un login e una password. L’URI è della forma jdbc:<protocollodb>:<parametri>. Ecco quindi la connessione al database:

In questo modo è avvenuta la nostra connessione al database. Se qualcosa non è andato a buon fine in questa connessione iniziale Java lancerà una SQLException che dovrà quindi essere opportunamente catturata dalla nostra applicazione. SQLException è utilissimo al programmatore visto che dispone di due metodi che permettono un veloce e semplice determinazione del problema.

Il metodo getErrorCode() di questa classe restituisce il codice d’errore deciso da chi ha fatto il database, quindi facilmente consultabile, mentre il metodo getSQLState() restituisce al programmatore una stringa contenente lo «stato» del DB in maniera conforme alle specifiche XOPEN o SQL99 (dipende dal DB), dando comunque al programmatore un semplice diretto messaggio che può portare subito all’individuazione del problema.

A questo punto Java ci offre tre semplici oggetti che semplificano la nostra vita per inviare e ricevere informazioni al database: Statement, PreparedStatement e ResultSet.

Lo Statement viene creato attraverso il metodo createStatement() di Connection. Ci sono due metodi importanti della classe Statement e sono executeQuery(String) ed executeUpdate(String). Il primo serve per interrogazioni al database (SELECT) mentre il secondo per inserimenti, aggiornamenti e cancellazioni (INSERT, UPDATE, DELETE).

Il metodo executeQuery(String) restituisce un ResultSet , un oggetto-tabella che rappresenta i dati selezionati dalla nostra interrogazione. Poi noi dobbiamo visitare questo ResultSet per vedere quali sono i dati e utilizzarli nel modo voluto. Questo oggetto viene letto come con un puntatore che grazie al metodo next() passa alla successiva riga della tabella che abbiamo avuto come risposta. Ecco un esempio di utilizzo:

Infine per ottimizzare la nostra applicazione utilizziamo i PreparedStatement. Facciamo un esempio, invece di scrivere 50 volte la query per l’update di 50 studenti nel database la scrivo una volta e poi le passo di volta in volta che voglio inserire dei nuovi studenti dei parametri:

Oltre a questo Java e database come Oracle permettono l’inserimento di classi e metodi Java all’interno del db, la scelta del livello di isolamento per il database, trigger, pool di connessioni, metodi di incapsulamento … ma questa è un’altra storia.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *