|
JDBC, i dati in linea
Dario de Judicibus
Le basi dati rappresentano le fondamenta di qualunque applicazione a livello
aziendale. Il connubio fra la portabilitα intrinseca di Java, la sua capacitα di operare
in rete e le classi JDBC per l’accesso alle basi dati costituisce un elemento chiave
nell’evoluzione di questo linguaggio
Estate 1996: Sun annuncia il primo rilascio del
kit JDBC, ovvero Java DataBase Connectivity. Si tratta di un evento importante nella sua
crescita perchΘ lo pone sempre pi∙ a livello di linguaggi pi∙ blasonati e consolidati
quali il C++. Come in tutte le evoluzioni di Java, il “Leit-motiv” Φ
rappresentato dal connubio fra le nuove funzionalitα e i punti di forza giα consolidati
del linguaggio quali la portabilitα e la connettivitα. Ma facciamo un passo
indietro…
C’era una volta la base dati, anzi, senza arrivare alla preistoria, c’era una
volta la base dati relazionale. In fondo l’elemento chiave dell’informatica Φ
appunto l’informazione, e l’informazione, spogliata della sua semantica, altro
non Φ che il dato: il numero, il carattere, la stringa, i mattoni che stanno alla base di
tutta la programmazione. Che vi si acceda dall’esterno, incapsulato in un oggetto, o
letto in tempo reale da un dispositivo apposito, il dato Φ la linfa vitale di qualunque
applicazione. Inutile forse sottolineare come le grandi applicazioni aziendali siano
soprattutto grandi elaboratrici di dati. Questi possono essere memorizzati in vari modi,
ma il pi∙ efficiente e, di fatto, quello che viene utilizzato di pi∙ oggi Φ appunto la
base dati relazionale. Una base dati altro non Φ che un insieme di dati a cui Φ stata
data una struttura ben definita; una guida telefonica Φ una base dati, cos∞ come lo Φ
un libro di ricette. Entrambi hanno un aspetto in comune: sono un insieme
d’informazioni strutturate secondo uno stesso schema. In un elenco telefonico avr≥
il cognome, il nome con un eventuale titolo, l’indirizzo e il numero di telefono.
Ognuna di queste informazioni rappresenta una scheda della base, o record.
Tuttavia, a volte, lo stesso record pu≥ contenere dati a loro volta collegati. Per
esempio, se un numero di telefono corrisponde a un apparecchio situato a Roma, il prefisso
sarα 06 (almeno fino a quando non avverrα l’annunciata rivoluzione dei prefissi);
tanto Φ vero che nell’elenco della capitale i numeri non riportano il prefisso per
ogni singolo utente. Analogamente, indicata la via e il numero civico, il riportare anche
il CAP dovrebbe costituire solo una comoditα del lettore dato che questa informazione
potrebbe comunque essere ricavata dall’indirizzo.
SQL standard di fatto
In un database relazionale, tutte le
informazioni collegate formano tabelline a parte. Questa struttura Φ di fatto trasparente
all’utente, che vede tutti i dati giα aggregati, o comunque decide come e cosa
vedere dell’aggregazione delle informazioni contenute nella base dati. Tale
operazione viene chiamata interrogazione (query) e viene generalmente realizzata
utilizzando un linguaggio speciale; quello oggi pi∙ usato, praticamente lo standard
“de facto” per tutti le grandi basi dati, Φ l’SQL. Non vogliamo qui
soffermarci su come funzionano le basi dati o l’SQL, ma per comprendere le JDBC pu≥
essere utile mostre un esempio di base dati relazionale spendendo due parole
sull’SQL.
Consideriamo un semplice indirizzario. Per ogni nome possiamo decidere di definire
alcuni campi come il nome e cognome della persona, l’indirizzo di casa, il numero di
telefono dell’abitazione. Dato poi che in teoria due persone con lo stesso nome e
cognome, tipo nonno e nipote, potrebbero abitare nella stessa casa, aggiungiamo anche un
semplice campo numerico che funge da identificativo del record, e lo chiamiamo chiave.
Otteniamo cos∞ una tabella come quella mostrata nella figura 1
Dato tuttavia che per telefonare abbiamo bisogno anche del prefisso, e per spedire una
lettera anche del CAP, e non volendo aggiungere tali campi alla tabella indirizzi perchΘ
si duplicherebbe inutilmente dei valori, creiamo una seconda tabella per questi codici
(figura 2).
A questo punto supponiamo di voler vedere tutte le persone con i rispettivi numeri di
telefono, completi di prefisso. Per prima cosa correliamo le due tabelle usando come campo
quello relativo alla cittα. Quindi definiamo un’interrogazione specificando i campi
che ci interessano. Se stiamo utilizzando Microsoft Access, la cosa apparirα pi∙ o meno
come in figura 3.
Notate ora come la figura evidenzi la relazione fra le due tabelle tramite il campo Cittα.
Se lanciamo l’interrogazione sulla base dati otterremo come risultato qualcosa di
simile a quanto mostrato in figura 4.
Per questo semplice esempio abbiamo usato un prodotto per PC e una base di pochi
record. Tuttavia nella realtα le aziende operano con enormi basi dati contenenti milioni
di record e strutturate su database aziendali come Oracle, DB2, Sybase o Informix, tanto
per nominarne alcuni. Per elaborarle vengono utilizzate grosse applicazioni in Cobol o C
che operano via SQL. Questo Φ appunto un linguaggio abbastanza semplice, ma molto potente
che permette di costruire interrogazioni anche molto complesse, creare tabelle,
aggiungere, modificare o cancellare record, e via dicendo. Per esempio, la nostra semplice
interrogazione sarebbe potuto essere espressa in SQL pi∙ o meno come appare nella figura
5 (MS Access SQL).
In realtα, ci sono diversi dialetti ed estensioni dell’SQL. Esiste comunque uno
standard, l’ANSI SQL92, che Φ implementato su tutti i grossi sistemi, anche se non
sempre Φ rispettato dalle versioni disponibili su piattaforme pi∙ piccole, come quelle
sviluppate per i PC.
Classi e architettura JDBC
Un’interrogazione SQL Φ generalmente
formata da almeno tre istruzioni. La prima, SELECT, seleziona quali campi sono
coinvolti. Un campo di una tabella Φ generalmente identificato dalla coppia NomeTabella.NomeCampo. La seconda, FROM, indica da quali tabelle i suddetti campi vanno presi.
Questo in quanto i campi possono essere anche identificati dal solo NomeCampo, se
appartengono tutti alla stessa tabella, o pi∙ semplicemente si pu≥ specificare SELECT * per
indicare tutti i campi di una tabella. La terza, WHERE, definisce le condizioni di selezione dei record. Per
esempio, per selezionare tutti i libri di fantascienza il cui prezzo Φ minore di 40.000
lire potremmo scrivere
SELECT Autore, Titolo, Editore, Prezzo
FROM Libri
WHERE Tipo LIKE 'SF' AND Prezzo < 40000
E veniamo alle classi JDBC. Il numero di
protocolli d’accesso alle basi dati Φ talmente elevato, e queste sono costruite
sulla base di architetture cos∞ differenti, che pensare di costruire un singolo insieme
di classi Java in grado di operare su qualunque base dati in qualunque sistema, anche
remotamente, sembrava improponibile. Dopo moltissime discussioni si arriv≥ a definire
un’architettura semplice, ma molto flessibile. Il modello Φ simile a quello ODBC
della Microsoft. In pratica l’architettura JDBC Φ costituita da due livelli. In alto
ci sono le API (Application Programming Interface) che permettono agli sviluppatori Java
di emettere comandi SQL nei confronti di una specifica base dati e di riceverne indietro
il risultato. Queste API comunicano con il livello inferiore, denominato Driver Manager.
Questo componente ha lo scopo di comunicare con un altro componente che rappresenta il
driver specifico per quella determinata base dati. Un po’ come si fa con le
stampanti. Il driver della stampante Φ un programma scritto generalmente da chi ha
costruito la stampante alla scopo di permettere la comunicazione con la macchina. Esso
inoltre presenta verso l’alto un’interfaccia standard capace di interagire con
un componente del sistema operativo chiamato Printer Manager. Quando stampiamo un
documento o una presentazione con una qualunque applicazione, la nostra applicazione
comunica al gestore delle stampanti su quale periferica intende stampare, e quindi
spedisce i dati di stampa sempre nella stesso modo, indipendentemente dalla stampante. Il
gestore verifica che un driver per quella stampante sia stato installato, e quindi
spedisce i dati in oggetto al driver specifico che si preoccuperα di convertirli nel
formato appropriato per la stampante selezionata.
PerchΘ JDBC e non ODBC?
L’architettura JDBC funziona allo
stesso modo. In particolare, data la somiglianza con quella ODBC, esiste un particolare
livello intermedio, chiamato JDBC/ODBC Bridge, che permette di usare un driver ODBC
con applicazioni JDBC, come illustrato nello schema.
PerchΘ allora, se il JDBC Φ cos∞ simile all’ODBC, non Φ stato utilizzato
quest’ultimo?
Secondo gli sviluppatori della JavaSoft vi sono vari motivi. Intanto, affermano,
l’ODBC Φ molto complesso, ha pochi comandi con molte opzioni, mentre
l’architettura Java preferisce basarsi su una serie di metodi semplici e immediati da
utilizzare, magari tanti, ma con pochi parametri. Inoltre, esso si basa moltissimo
sull’utilizzo di puntatori a void e su altre caratteristiche del C che trovano scarso o
nessun riscontro in Java. Il pesante utilizzo di puntatori multipli o di tecniche basate
su deriferimenti, rende troppo difficile importare tale architettura in Java. Comunque
sia, le classi JDBC si sono aggiunte alle giα svariate classi di Java, diventando ben
presto un punto di riferimento fondamentale per chiunque voglia sviluppare applicazioni
basate sui dati in questo linguaggio.
Ma quali sono i vantaggi delle classi JDBC?
Innanzitutto esse permettono di scrivere applicazioni Java che possono accedere a
qualunque base dati semplicemente utilizzando istruzioni SQL, non solo quelle standard, ma
di fatto anche qualunque estensione proprietaria sviluppata. Il tutto continuando ad
avvalersi di tutti i vantaggi del linguaggio Java, come la capacitα di girare su
qualunque piattaforma, la robustezza garantita dai meccanismi di sicurezza e dalla
gestione delle eccezioni, la possibilitα di operare in locale come in remoto dato dalle
classi RMI. Il meccanismo Φ cos∞ flessibile che se uno sposta i dati da una base dati ad
un’altra, deve solo cambiare il driver JDBC e l’applicazione continuerα a
funzionare regolarmente con la nuova base dati. L’altro aspetto Φ che, nonostante il
meccanismo del Driver Manager garantisca un’interfaccia comune a tutti i sistemi e le
basi dati, la presenza di driver JDBC specifici per ogni base dati supportata garantisce
un utilizzo ottimale delle caratteristiche specifiche di quella base dati.
Applet si, applet no
In effetti, le classi JDBC sono usate
principalmente con le applicazioni.; ma possono essere impiegate anche in un applet. In
questo caso, tuttavia, risentono delle restrizioni tipiche delle applet scaricate da un
sistema remoto. Per esempio, un’applet che usa delle classi JDBC pu≥ aprire una
connessione con una base dati remota solo se questa si trova sul server dal quale
l’applet Φ stata scaricata. Inoltre, essa non pu≥ utilizzare in alcun modo
informazioni presenti sul client. Persino il driver JDBC, qualora scaricato dal sistema
remoto insieme all’applet, pu≥ funzionare solo con connessioni con lo stesso server
dalla quale Φ stata scaricata. Ci≥ significa che il server dovrebbe fungere sia da
server Web sia da server dati, il che, spesso, Φ un po’ eccessivo in termini di
carico. Naturalmente, esistono vari modi di aggirare legalmente il problema, ma tutti si
basano su un’opportuna riconfigurazione del server, cosa non sempre cos∞ semplice da
fare. Un’alternativa potrebbe essere quella di utilizzare le classi RMI per collegare
l’applet a un server intermedio il quale, utilizzando le classi JDBC, interagisce
direttamente con la base dati. Tuttavia, si tratta di una soluzione che potrebbe creare
problemi a livello di prestazioni. Per il momento ci fermiamo qui. Nei prossimi articoli
torneremo a parlare di JDBC illustrando qualche esempio di codice e ulteriori dettagli
relativi a classi e metodi. |