iBatis: un framework Java per la persistenza e l’OR mapping

In questo articolo viene spiegato l’utilizzo di iBatis, famoso framework che ci permette di gestire più facilmente lo strato di connessione verso il database

L’uso dei database è diventato indispensabile per qualsiasi programmatore che vuole sviluppare un qualsiasi applicativo, anche semplice. Java, come molti linguaggi di programmazione mette a disposizione una serie di librerie molto valide (JDBC) per operare con il proprio database preferito. Sfortunatamente queste librerie non si adattano molto allo stile di programmazione OOP di cui Java è un suo rappresentante, pertanto sono presente su piazza molte soluzioni più o meno valide per mascherare lo stile relazionale dei database con quello orientato agli oggetti di Java.

La prima soluzione che mi viene in mente è senza dubbio HIBERNATE. Ottimo per la sua enorme flessibilità e per la libertà che offre al programmatore di operare al meglio delle proprie logiche di business. Non posso non citare pBeans. Certamente progetto semplice e non paragonabile ad HIBERNATE ma molto interessante. Facile da usare e, sopra ogni cosa, leggero, il che non guasta mai.

Anche Apache ha presentato la sua alternativa. Si chiama iBatis. Il progetto può essere scaricato con licenza Apache all’indirizzo internet http://ibatis.apache.org/. Nella Home page del progetto noterete subito una cosa molto interessante. Le librerie di iBatis sono presenti per più linguaggi di programmazione; Java, .Net e Ruby. Questo favorisce il suo utilizzo all’interno degli ambienti produttivi e permette di sviluppare differenti applicazioni con linguaggi diversi che per esempio utilizzano tutti lo stesso database mappato da un solo framework.

ibatis

ibatis

 

Come si può vedere dalla figura, iBatis Data Mapper Framework si avvale di uno o più descrittori XML per mappare il database con il supporto, qualora lo si volesse di file di tipo properties per fornire un supporto ai file XML per la distribuzione della configurazione del sistema di mapping.

Il grande vantaggio nell’utilizzare iBatis sta nel fatto che le stringhe SQL che di solito si usano all’interno del codice sorgente vengono scritte esternamente al codice sorgente all’interno di moduli XML da noi definiti e richiamati dal programmatore ogni volte che servono tramite un semplice id identificativo. La mappatura della tabella viene realizzata con la tradizionale scrittura di una classe di tipo JavaBean. Questa permette al programma di vedere il database come una classe Java.

Per questo articolo ho deciso di sviluppare una semplice tabella, con un qualsiasi database, che si occupi di gestire il login di un utente. Le operazione che andremo a compiere sul database sono le solite quattro operazioni che da sempre ci assillano: INSERT, UPDATE, SELECT e DELETE. Aggiungeremo anche un operazione di SELECT COUNT(*) che ci permetterà di ottenete il numero di elementi (record) presenti all’interno della nostra tabella.

Prima di iniziare a scrivere il codice sorgente per lavorare con la nostra tabella dobbiamo crearne una che chiameremo LOGIN, composta dai seguenti campi:

  • LOG_USERNAME ==> varchar(20) not null
  • LOG_PASSWORD ==> varchar(10) not null
  • LOG_LAST_ACCESS ==> date null

 

LOG_USERNAME contiene il nome dell’utente, LOG_PASSWORD contiene la password ci accesso e LOG_LAST_ACCESS ci dice la data dell’ultima volta noi siamo stati accettati dal sistema.

A questo punto è necessario iniziare a chiarire le cose. Per utilizzare iBatis nelle vostre applicazioni dovrete, come prima cosa, importare le librerie del progetto. Successivamente dovrete iniziare, tramite il vostro IDE di lavoro, a scrivere un file XML di descrizione. Non importa quale nome diate al vostro file di configurazione generale, purché sia scritto in modo corretto. Io l’ho chiamato SqlMapConfig.xml. Per gli utenti che usano Eclipse esiste un plugin, che si trova linkato dal sito ufficiale di iBatis, che aiuta a sviluppare questo file. Per gli utenti di NetBeans non esiste ancora un estensione pronta all’uso. Un possibile risultato di tale file è il seguente:

Come si evince, nel file sono mappate alcune informazioni importanti per l’uso del nostro database e altre non essenziali. L’intero tag settings non è obbligatorio all’interno del file di configurazione, se non presente o parzialmente implementato questo utilizza le impostazioni di default di iBatis. Per maggiori dettagli si rimanda alla documentazione ufficiale della libreria.

Il tag successivo è transactionManager nel quale viene richiesto il tipo di connettore da utilizzare come transaction manager. Le possibilità sono: JDBC, JTA e EXTERNAL. Per EXTERNAL si intende che iBatis utilizzerà il transaction manager del engine in uso. Subito dopo viene specificato il dataSource. Questo può essere SIMPLE, DBCP, JNDI. Con SIMPLE si intende che verrà utilizzata l’implementazione base del pooling del DataSource, che è l’ideale per ogni tipo di connessione. Con la parolina magina DBCP si utilizzerà il Jakarta DBCP (DataBase Connection Pool) ideale quando l’applicazione o il web container non hanno un implementazione del DataSource. JNDI non ha bisogno di presentazione, presumo che molti conoscano già questo sistema.

Successivamente vengono inseriti i tag di property definiti dai campi nome/valore. I campi da me inseriti sono obbligatori mentre tutti gli altri, che troverete sulla documentazione sono del tutto facoltativi. Come si vede vengono inseriti i valori necessari minimi per poter connettersi al proprio database.

Per finire troviamo il tag sqlMap. Questo permette ai programmatori di mappare le istruzioni di ogni singola tabella su file XML ben distinti anziché scrivere tutto all’interno del file di configurazione. Questo aumenta enormemente la leggibilità del file e né snellisce la sua gestione. Pertanto con questo tag possiamo indicare i file operativi più specifici inserendo semplicemente il path di appartenenza.

Si possono applicare molte modifiche a questa struttura di alcune molto semplici e interessanti sono; distribuire i file di configurazione del database in un file esterno di properties o modificare il transaction manager o il data source con uno personalizzato.

dove il file config.properties è cosi definito

Questo ci permette di modificare solo un file di configurazione senza toccare il file sqlMapConfig.xml. Questa soluzione mostra come si possa operare sul file sqlMapConfig.xml, tramite un file di supporto esterno, senza dover cambiare i parametri che non vogliamo mai modificare, agendo solo su quelli che richiedono modifiche nel futuro.

Questo conclude la trattazione del file sqlMapConfig.xml e apre le porte ad un nuovo file del quale non abbiamo ancora parlato; il file Login.xml che come si vede dal tag sqlMap si trova all’interno di una directory denominata tables. Questo non è obbligatorio, si poteva creare il file sulla medesima root del sqlMapConfig.xml. Per motivi di semplicità e di chiarezza io preferisco sempre inglobare questi file all’interno di una directory che mi specifica il suo contenuto.

Il file Login.xml è così descritto:

A questo file dobbiamo associare una classe Java scritta nel seguente modo:

Come si vede la classe contiene semplicemente metodi di get e di set per i rispettivi elementi che la compongono. Non credo debba essere descritta nel dettaglio.

Il file Login.xml invece richiede qualche parola di più. Per iniziare il tag sqlMap contiene un campo chiamato namespace. Questo campo specifica il namespace del contenuto del file, in questo caso Login. Successivamente cadono all’occhio alcune cose abbastanza chiare. Esistono tag che definiscono le quattro operazioni elementari quali SELECT, UPDATE, INSERT e DELETE. Questo ci mostra che ogni operazione deve essere contenuta all’interno del suo tag specifico. Seconda cosa, tutti i tag hanno un identificativo unico definito dal attributo “id”. Questo assegna il nome alla stringa SQL da lanciare. E per finire compaiono sempre, o quasi, gli attributi “resultClass” e “parameterClass”. Il primo permette di ottenere il tipo di oggetto come output dell’operazione il secondo, invece, ci permette di passare uno o più parametri all’interno della stringa SQL.

Per semplicità ho utilizzato un tag denominato “typeAlias”. Questo permette di identificare un oggetto con un nome più semplice. Nel nostro caso, anziché scrivere sempre java.lang.String ho preferito scrivere semplicemente string attribuendo con typeAlias a string il valore di java.lang.String.

Iniziando, nel tag select identificato dall’id “getPassword” viene passata alla stringa SQL un valore di tipo String e viene restituito un valore unico, anche questo di tipo String. Il valore passato alla stringa SQL viene scritto se è compreso tra due #. Il tipo di variabile che si sceglie in questo caso è del tutto indifferente in quanto il valore è singolo, quindi anziché scrivere #value# potevo scrivere #toto# ed avrei ottenuto il medesimo effetto.

Nel secondo esempio di select, identificato con l’id getLogin si richiede di ritornare l’intero contenuto del record cercato e di mapparlo con la classe da noi scritta. Per fare questo si attribuiscono i riferimenti colonna – variabile con COLONNA as VARIABILE_CLASSE.

L’ultimo select, quello con id “getLogins”, invece vuole avere un elenco di tutti gli elementi presenti nella nostra tabella. Pertanto ci si avvale del tag “resultMap” per mappare solo le colonne che ci interessano con le relative variabili della classe Login e solo dopo si crea un riferimento al tag select tramite l’attributo “resultMap”. Questo genererà un oggetto di tipo List che conterrà tanti oggetti Login quanti i records della tabella.

Per i tag “insert” e “delete” la considerazione è unica. Dal momento che non viene passato un solo elemento, bensi un oggetto che è una collezione di elementi, si deve assolutamente utilizzare il corretto nome della variabile della classe, in questo caso Login. In altre parole, quando iBatis legge, in questo caso, #username# si preoccuperà lui a prelevare il valore della variabile username della classe Login con il metodo getUsername(). Provate a scrivere, per esempio, #value# otterrete un errore di lettura del file.

Una soluzione per esportare i dati che iBatis mette a disposizione è:

E il risultato di questo statement è il seguente

Comodo, non credete?

Ora dobbiamo preoccuparci di come fare a operare tramite Java con tutta questa roba che abbiamo scritto ed imparato fino ad ora. Per prima cosa, l’oggetto che permette di operare è SqlMapClient il quale è un oggetto di servizio, cioè un thread safe e dalla lunga vita. Pertanto avrete bisogno di istanziarlo solo una volta nella vostra vita del programma. Una soluzione utile potrebbe essere la seguente

A questo punto potete operare con il vostro database. L’oggetto sqlMap mette a disposizione metodi per risolvere ogni problema. Se per esempio voi volete ottenere tutta la lista dei records della tabella basta solo:

dove con la prima stringa si identifica l’id da chiamare e con la seconda l’oggetto da passare alla stringa SQL.
E adesso buon lavoro.

Lascia un commento

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