MokaByte
Numero 25 - Dicembre 98
|
|||
|
|
||
Marangoni Rosanna |
|
||
Il nuovo JDK 1.2 ha ampliato le funzionalità e le caratteristiche di JDBC, l’interfaccia java per database SQL. In questo articolo analizzeremo alcune delle novità introdotte in JDBC 2.0. Con il nuovo
JDK 1.2 (Java Developement Kit) le JDBC API che costituiscono l’interfaccia
java ai database, sono state riscritte per migliorare le funzionalità
fornite con la versione di JDBC 1.0 e per ottimizzare le prestazioni durante
l’esecuzione. Inoltre, sono state introdotte alcune nuove peculiarità
che consentono di utilizzare JDBC con nuovi strumenti java quali Java Transaction
Service (JTS), the Java Naming and Directory Interface (JNDI), JavaBeans
e Enterprise Java-Beans (EJB).
JAVA E I DATABASE: NASCE JDBC. L’attenzione
generale delle applicazioni realizzate negli ultimi anni è rivolta
verso l’accesso alle basi di dati sia in locale che in remoto. Questo si
può notare nel grande sviluppo del commercio elettronico tramite
Internet ma soprattutto nella grande diffusione di piccole applicazioni
per il singolo utente: dal guestbook presente in molte homepage agli elenchi
delle pubblicazioni o delle discografie.
COSA C’E’ DI NUOVO IN JDBC 2.0? Dopo questa breve
introduzione sull’evoluzione di JDBC, ci possiamo concentrare sullo scopo
di questo articolo, ossia sulle novità introdotte nella nuova versione
del JDK.
Riassumendo, le caratteristiche introdotte sono le seguenti:
LA CONNESSIONE AL DATABASE. Prima di ottenere la connessione al database, è necessario ricordarsi di importare il package java.sql in modo da poter utilizzare le classi e le interfacce di JDBC. Per questo, nelle linee di codice del programma dedicate all’importazione dei package, andrà specificato: import java.sql.*;Ottenere una connessione al database tramite JDBC è abbastanza semplice ed indipendente da quale tipo di DBMS si stia utilizzando. E’ necessario solamente indicare all’applicazione, tramite il DriverManager, quale driver utilizzare e farsi rilasciare un oggetto Connection che servirà per dialogare con la base dati. E’ da notare che per identificare il database è necessario specificare l’URL, ossia l’indirizzo verso il quale tentare la connessione. Questa stringa può variare in base al tipo di driver utilizzato, e, alcune volte, può richiedere anche la specificazione di login e password dell’utente. Le linee di codice che realizzano queste procedure iniziali per un database ODBC sono le seguenti: Se si dovesse utilizzare un driver per Database MSQL, le linee di connessione sarebbero: Ovviamente, la ricerca di un driver e il tentativo di connessione potrebbero non andare a buon fine e generare, di conseguenza, un’eccezione. Per questo, è necessario inserire le istruzioni appena viste, in un try-catch in questo modo: All’interno del secondo try-catch, andranno inserite anche tutte le istruzioni che intendiamo eseguire sul database, quali un’interrogazione, una modifica o qualsiasi altra operazione. L’OGGETTO Statement. Una volta ottenuta la connessione al database, è necessario creare un oggetto Statement che permetta di sottoporre al DBMS le nostre instruzioni SQL. Il modo più semplice per ottenere uno Statement, data una connessione con, è il seguente: In seguito, tramite i metodi st.executeQuery() e st.executeUpdate() si possono eseguire operazioni rispettivamente di interrogazione o modifica (creazione tabelle, inserimento dati, cancellazione dati, etc.) sulla base di dati. Esistono 3 tipi di Statement: Statement, PreparedStatement, CallableStatement. Senza occuparci nel dettaglio delle differenze che intercorrono tra i tre diversi tipi di oggetto, possiamo dire che il loro scopo è comunque quello di poter fornire dei metodi per interagire con la base di dati e che quello che li caratterizza è solamente la possibilità o meno di “preparare” una Query pre-compilata nella quale è sufficiente solo inserire i parametri. LO SCROLLABLE RESULT SET L’esecuzione del metodo st.executeQuery() su un oggetto Statement, crea un nuovo oggetto chiamato ResultSet contenente la tabella che costituisce il risultato dell’interrogazione sulla base dati. Fino alla versione 1.0, l’unico modo per scorrere il ResultSet era il metodo next() che spostava il puntatore alle tuple del ResultSet restituendo un booleano per indicare se fosse raggiunta o meno la fine della tabella. Nel caso di una semplice base di dati composta da una Tabella AZIONI contenente i campi NOME (String) e PREZZO (Float), una query poteva essere realizzata in questo modo: Come si può notare, il ciclo scorre il ResultSet dall’inizio alla fine, preleva i dati tramite i metodi getXXX e quindi li stampa a video. Questo oggetto è stato ampliato nella nuova versione delle JDBC API in modo da poter scorrere i risultati in entrambi i sensi; quindi verso il basso e verso l’alto tramite l’introduzione del metodo rs.previous(). Inoltre sono stati inseriti altri metodi interessanti quali:
Ricordiamo che è buona norma inserire alla fine del corpo del programma (prima dell’ultimo catch, per intenderci) le linee di codice che permettono la chiusura rispettivamente del ResultSet, Statement e Connection. L’oggetto ResultSet può essere reso nuovamente non-scrollable tramite l’argomento TYPE_FORWARD_ONLY. Inoltre esistono due tipi di ResultSet scrollable: Sensitive e Insensitive. La differenza tra i due tipi di oggetto, consiste nella capacità o meno di vedere le modifiche effettuate sul database mentre il ResultSet è aperto. Ci occuperemo di questo nella parte dedicata alla Visualizzazione delle modifiche. L’UPDATABLE RESULT SET Un’altra caratteristica
inserita nell’oggetto Result Set, consiste nella possibilità di
modificare i dati di una Tabella senza ricorrere ad una query SQL.
Con l’Updatable ResultSet, è invece sufficiente spostarsi sulla riga voluta (è quindi necessario che il ResultSet sia anche Scrollable) e quindi lanciare il metodo updateXXX corrispondente al tipo di dato da modificare. Il codice per ottenere uno Scrollable and Updatable ResultSet, si deve inserire il parametro ResultSet.CONCUR_UPDATABLE come argomento durante l’esecuzione del metodo createStatement() sulla Connessione. Per rimuovere la possibilità di modificare il ResultSet si deve specificare ResultSet.CONCUR_READ_ONLY. Di default, se non viene specificato nessun paramentro a riguardo, il ResultSet viene creato non Updatable. Un esempio di utilizzo potrebbe essere: Il metodo updateRow() serve per rendere effettive le modifiche inserite nel metodo updateXXX. Esiste anche il metodo cancelRowUpdates() che annulla le modifiche indicate con updateXXX(), ma questo è possibile solamente prima di un updateRow(). Una volta confermate le modifiche sul database, infatti, non sarà più possibile annullarle. INSERIRE E CANCELLARE TUPLE SENZA UTILIZZARE CODICE SQL Oltre alla modifica
dei dati, è anche possibile inserire e cancellare delle tuple dalle
tabelle del Database, senza utilizzare delle query SQL. Ribadiamo comunque,
che è sempre possibile utilizzare l’SQL per questi tipi di aggiornamenti
proprio come avveniva nella precedente verisione di JDBC. Proprio per questo
motivo il codice già realizzato con JDBC 1.0 continua ad essere
compilato ed eseguito anche dalle nuove API.
Con le nuove funzionalità di JDBC sono stati introdotti i metodi moveToInsertRow(), moveToCurrentRow(), insertRow() e deleteRow() che possono essere utilizzati al posto dell’SQL. Ad esempio per inserire una tupla, sarà necessario posizionarsi sulla riga da inserire tramite il metodo moveToInsertRow(). Quindi, tramite il metodo updateXXX(), si dovranno inserire i dati dei campi. L’effettivo inserimento avviene tramite il metodo insertRow() che provvede alla scrittura della nuova tupla sul database. Per riposizionarsi sulla riga corrente prima dell’inserimento, esiste il metodo moveToCurrentRow(). E’ importante notare che questo metodo è utilizzabile solo se si è posizionati sulla riga di inserimento. In modo del tutto analogo, il metodo deleteRow() permette la cancellazione di una tupla. In questo caso, per posizionarsi sulla tupla da eliminare, può essere d’aiuto utilizzare i metodi visti per lo Srollable ResultSet quali previous(), absolute(), relative(), etc. LA VISUALIZZAZIONE DELLE MODIFICHE Per quanto riguarda
l’aggiornamento del ResultSet, devono essere puntualizzate alcune cose:
fin tanto che il ResultSet non viene chiuso e quindi ricreato, le modifiche
effettuate sul database non sono visibili. Questo potrebbe rivelarsi un
grosso inconveniente dal punto di vista della consistenza dei dati.
dove con rappresenta un oggetto Connection. Tramite questo isolation level, il ResultSet non visualizzerà i cambiamenti prima che questi non siano stati effettivamente inviati al database, ma questo può creare problemi di inconsistenza del database. L’interfaccia DatabaseMetaData offre la capacità di determinare con procisione le capacità esatte supportate da un Result Set tramite i metodi:
Inoltre, se una modifica è visibile, esistono anche i metodi rs.wasUpdated(), wasDeleted() e wasInserted() che servono per determinare se una tupla è stata modificata da un’operazione di modifica, cancellazione o inserimento da quando il ResultSet è stato aperto. Per essere sicuri di rendere visibili tutte le modifiche riguardanti una tupla precisa del ResultSet, comprese le più recenti, si può utilizzare anche il metodo ResultSet.refreshRow(). MODIFICA DELLA BASE DATI TRAMITE PROCEDURE BATCH Nelle JDBC 1.0 API, era possibile unire diverse query in modo tale che fossero tutte eseguite in una transazione sola. Questo era consentito grazie all’impostazione a false dell’setAutoCommit(), che di default è true, e che permette di inserire diverse update che vengono effettivamente eseguite solamente col metodo com.commit(). Il codice che permette di realizzare questo è: Nonostante sia ancora possibile utilizzare questo espediente, le JDBC 2.0 API mettono a disposizione un sistema nuovo che prevede l’impostazione una sequenza Batch direttamente da Statement. Ponendo sempre l’autoCommit a false, si possono associare ad uno Statement delle operazioni tramite il metodo st.addBatch(querySQL), per poi eseguirle con st.executeBatch(). E’ interessante notare che esecuteBatch(), ritorna un array di interi che indicano quante tuple sono state modificate per ogni operazione contenuta nella procedura Batch. Per azzerare la lista dei comandi, è disponibile anche il metodo clearBatch(). Come si può facilmente notare, l’esecuzione di molte istruzioni in una procedura può comportare dei problemi di inconsistenza che non erano stati previsti. Questi errori portano alla generazione di eccezioni diverse in base alla natura stessa degli inconvenienti che sono stati generati. Ad esempio: se un’operazione contenuta nella procedura dovesse ritornare un ResultSet, questo, ovviamente, non potrebbe essere inserito nell’array di updateCount. In questo caso viene generata un’SQLException. Se, al contrario, un’operazione non può essere eseguita per qualche motivo, allora viene generata una BatchUpdateException. UTILIZZO DEI TIPI DI DATI SQL3 I tipi di dati
che vengono comunemente definiti SQL3 fanno parte delle nuove specifiche
ANSI/ISO SQL standard. Le nuove JDBC 2.0 API, si sono adeguate a questo
nuovo standard introducendo anche i metodi per la trattazione di questi
tipi di dati che, quindi, possono essere utilizzati e manipolati come tutti
gli altri tipi di dati che erano già presenti.
Clob descrizione = rs.getClob(“DESCR”);Per quanto riguarda gli UDT, possiamo dire che sono molto simili ai tipi strutturati presenti in java e che corrispondono all’istruzione SQL CRATE TYPE. Un esempio potrebbe essere rappresentato dalle coordinate di un punto. In questo caso si utilizza una struttura dati che è costituita da due valori: la coordinata x e la coordinata y. L’unica cosa da notare è che nel caso delle Struct, è necessario eseguire il casting che trasformi l’oggetto restituito da getObject() in un oggetto Struct. CONCLUSIONI Come abbiamo
potuto notare in questo articolo, la filosofia di JDBC di essere semplice
da usare continua ad essere seguita fedelmente. Infatti, non solo sono
state mantenute le caratteristiche di JDBC 1.0 per garantire una certa
continuità, ma si è favorita ulteriormente l’indipendenza
dai DBMS utilizzati e la capacità di modificare e trattare i dati.
I nuovi metodi e le nuove interfacce, permettono di utilizzare il database
nella maniera più semplice possibile, fornendo anche nuovi strumenti
per “bypassare” le istruzioni SQL.
BIBLIOGRAFIA [1] Giovanni
Puliti, “Il nuovo JDK 1.2”, Dev Settembre 1998.
|
Marangoni Rosanna e' diplomanda in Ingegneria Informatica ed Automatica presso l'Universita' degli Studi di Padova con una tesi sulla multimedialita' nella comunicazione aziendale. Nel periodo 1997/98, ha sostenuto due esami su JAVA e da allora continua ad interessarsi degli sviluppi successivi. |
MokaByte Web 1998 - www.mokabyte.it MokaByte ricerca nuovi collaboratori. Chi volesse mettersi in contatto con noi può farlo scrivendo a mokainfo@mokabyte.it |