Introduzione
ORMLite fornisce delle funzionalità leggere per il problema dell'ORM (Object Relational Mapping) tra classi Java e un database SQL. Seppure esistono soluzioni ORM molto più mature (come per esempio Hibernate), questa libreria risulta utile soprattutto per la la semplicità di utilizzo e la complessità ridotta. Quest'ultima caratteristica la rende adatta per contesti dove le risorse sono limitate (smartphone). Insieme a questo vantaggio, nella documentazione reperibile nel sito ufficiale si offre ampio supporto al mondo Android.
Prima di procedere è bene precisare che a causa della mancanza del supporto per i JDBC in Android, ORMLite utilizza in maniera diretta le API native per l'accesso ai database SQL.
Download e import
La prima operazione da compiere è quella di scaricare l'ultima release dal seguente link http://ormlite.com/releases/. La versione di riferimento per questa guida è la 4.48 e risale a Dicembre 2013.
Come si può notare una volta cliccato il link, vi sono tre file jar da poter scaricare identificati con i seguenti nomi: Core, JDBC e Android.
Per l'utilizzo dell'ORM in una applicazione Android è sufficiente scaricare i soli file jar relativi al core e Android.
Dopo aver creato il progetto bisogna aprire il pannello della configurazione del Build Path (scheda Libraries) e aggiungere come External JARs i due file scaricati.
Creare le classi persistenti
Per utilizzare il concetto di persistenza attraverso ORMLite si utilizzano le annotazioni di Java.
Per fare questo ho preparato un esempio banale di una ipotetica classe Studente:
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
@DatabaseTable(tableName = "studente")
public class Studente {
@DatabaseField(id = true)
private String numeroMatricola;
@DatabaseField
private String nome;
@DatabaseField
private String cognome;
public Studente()
{
}
public String getNumeroMatricola() {
return numeroMatricola;
}
public void setNumeroMatricola(String numeroMatricola) {
this.numeroMatricola = numeroMatricola;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getCognome() {
return cognome;
}
public void setCognome(String cognome) {
this.cognome = cognome;
}
}
- L'import delle librerie.
- Costruttore vuoto.
Progettare uno strato per la persistenza
A questo punto la domanda alla quale bisognerà trovare risposta è:
Esiste un modo per progettare uno strato con la responsabilità di gestire la persistenza in maniera tale da ottimizzare il riuso del codice? O meglio, posso realizzare un componente indipendente che posso utilizzare in tutti i miei progetti Android per la gestione della persistenza?
L'idea di massima è quella di creare un package di nome persistence accessibile attraverso una sola classe identificata con il suffisso Facade (dal pattern omonimo). Tutti i messaggi scambiati con lo strato passeranno attraverso questa classe. Questo è un aspetto cruciale per il riuso in quanto tutto quello che è nel sottosistema deve essere inesistente per le classi utilizzatrici di esso. Un esempio di una ipotetica classe Facade con le funzionalità di salvataggio, cancellazione e recupero di oggetti è mostrato nella figura che segue:
Per qualsiasi oggetto che venga passato ai metodi indicati, lo strato persistence deve essere in grado di eseguire la funzionalità prevista.
Ma come faccio ad implementare tutto questo?
Ho realizzato una piccola implementazione che per stimolare il lettore NON condividerò qui sul mio blog (se volete le classi con il codice potete scrivere come commento la vostra mail e ve le manderò senza problemi).
Piuttosto vi condivido i passi chiave:
1) Recuperate l'esempio intitolato HelloAndroid di ORMLite e scaricate i file HelloAndroid e DatabaseHelper (il link è il seguente http://ormlite.com/android/examples/)
2) Aggiungeteli al vostro progetto con l'accortezza di creare un package persistence e porvi all'interno la classe DatabaseHelper.
3) Create una classe PersistenceFacade nel package persistence che rispetti il pattern Singleton in questo modo (notate la parola chiave static per il metodo e l'attributo):
public static PersistenceFacade instance = null;
public static PersistenceFacade getInstance()
{
if (instance==null)
instance=new PersistenceFacade();
return instance;
}
private PersistenceFacade()
{
}
4) Bisogna modificare alcuni metodi del DatabaseHelper. Qui viene il bello e preferisco che il lettore "provi" a realizzarlo. (Nel caso in cui non ci riusciate non esitate a chiedere ulteriori chiarimenti)
L'idea di base è quella di porre i nomi delle classi persistenti in una risorsa esterna, sfruttando i file XML tipici di Android. Sarà sufficiente utilizzare la reflection per fare in modo che lo strato persistence non dipenda dal nostro strato di dominio. Leggendo dalla risorsa esterna le classi da rendere persistenti il metodo onCreate della classe DatabaseHelper creerà tutte le tabelle necessarie.
Ciò è un vantaggio in relazione a modifiche future o riuso del codice: aggiungere una riga di XML è sufficiente per poter creare la tabella sul proprio db.
5) A questo punto non rimane altro che scrivere gli infiniti metodi che si vogliono utilizzare per la persistenza in maniera del tutto generale (sfruttando il polimorfismo). Un esempio di metodo save sarà:
public void Save(Object obj)
{
RuntimeExceptionDao<Object, Integer> simpleDao = (RuntimeExceptionDao<Object, Integer>) this.getDbHelper().getSimpleDataDao(obj.getClass().getName());
simpleDao.create(obj);
}
Il lettore può notare che le righe di codice sono ridotte a due e l'utilizzo dell'Object consente il riuso del metodo per qualsiasi tipo di oggetto si voglia rendere persistente purchè sia stato dichiarato nel file XML menzionato nel punto 4.
A questo punto il lavoro è completo. Sarà sufficiente ampliare il numero di metodi pensati per la persistenza come per esempio Delete, GetAll, etc...
Ai lettori più curiosi che sono arrivati fino a questo punto dell'articolo chiedo:
Pro e Contro di questo approccio?
- Costruttore vuoto.
Progettare uno strato per la persistenza
A questo punto la domanda alla quale bisognerà trovare risposta è:
Esiste un modo per progettare uno strato con la responsabilità di gestire la persistenza in maniera tale da ottimizzare il riuso del codice? O meglio, posso realizzare un componente indipendente che posso utilizzare in tutti i miei progetti Android per la gestione della persistenza?
L'idea di massima è quella di creare un package di nome persistence accessibile attraverso una sola classe identificata con il suffisso Facade (dal pattern omonimo). Tutti i messaggi scambiati con lo strato passeranno attraverso questa classe. Questo è un aspetto cruciale per il riuso in quanto tutto quello che è nel sottosistema deve essere inesistente per le classi utilizzatrici di esso. Un esempio di una ipotetica classe Facade con le funzionalità di salvataggio, cancellazione e recupero di oggetti è mostrato nella figura che segue:
Per qualsiasi oggetto che venga passato ai metodi indicati, lo strato persistence deve essere in grado di eseguire la funzionalità prevista.
Ma come faccio ad implementare tutto questo?
Ho realizzato una piccola implementazione che per stimolare il lettore NON condividerò qui sul mio blog (se volete le classi con il codice potete scrivere come commento la vostra mail e ve le manderò senza problemi).
Piuttosto vi condivido i passi chiave:
1) Recuperate l'esempio intitolato HelloAndroid di ORMLite e scaricate i file HelloAndroid e DatabaseHelper (il link è il seguente http://ormlite.com/android/examples/)
2) Aggiungeteli al vostro progetto con l'accortezza di creare un package persistence e porvi all'interno la classe DatabaseHelper.
3) Create una classe PersistenceFacade nel package persistence che rispetti il pattern Singleton in questo modo (notate la parola chiave static per il metodo e l'attributo):
public static PersistenceFacade instance = null;
public static PersistenceFacade getInstance()
{
if (instance==null)
instance=new PersistenceFacade();
return instance;
}
private PersistenceFacade()
{
}
4) Bisogna modificare alcuni metodi del DatabaseHelper. Qui viene il bello e preferisco che il lettore "provi" a realizzarlo. (Nel caso in cui non ci riusciate non esitate a chiedere ulteriori chiarimenti)
L'idea di base è quella di porre i nomi delle classi persistenti in una risorsa esterna, sfruttando i file XML tipici di Android. Sarà sufficiente utilizzare la reflection per fare in modo che lo strato persistence non dipenda dal nostro strato di dominio. Leggendo dalla risorsa esterna le classi da rendere persistenti il metodo onCreate della classe DatabaseHelper creerà tutte le tabelle necessarie.
Ciò è un vantaggio in relazione a modifiche future o riuso del codice: aggiungere una riga di XML è sufficiente per poter creare la tabella sul proprio db.
5) A questo punto non rimane altro che scrivere gli infiniti metodi che si vogliono utilizzare per la persistenza in maniera del tutto generale (sfruttando il polimorfismo). Un esempio di metodo save sarà:
public void Save(Object obj)
{
RuntimeExceptionDao<Object, Integer> simpleDao = (RuntimeExceptionDao<Object, Integer>) this.getDbHelper().getSimpleDataDao(obj.getClass().getName());
simpleDao.create(obj);
}
Il lettore può notare che le righe di codice sono ridotte a due e l'utilizzo dell'Object consente il riuso del metodo per qualsiasi tipo di oggetto si voglia rendere persistente purchè sia stato dichiarato nel file XML menzionato nel punto 4.
A questo punto il lavoro è completo. Sarà sufficiente ampliare il numero di metodi pensati per la persistenza come per esempio Delete, GetAll, etc...
Ai lettori più curiosi che sono arrivati fino a questo punto dell'articolo chiedo:
Pro e Contro di questo approccio?
0 commenti:
Posta un commento