Introduzione

Quando ci si trova a dover lavorare con tecnologie mai utilizzate prima, l'approccio di molti programmatori è quello di riutilizzare codice scritto da terzi, spesso meccanicamente, senza capire a fondo ciò che si sta facendo. Se la tecnologia in questione è Hibernate, un mancato approfondimento di alcuni aspetti tecnici, può portare a due problemi principali: da un lato errori in esecuzione riguardo ai quali non esiste in rete un'adeguata documentazione; dall'altro, il non sfruttare appieno le potenzialità reali del framework.

Le potenzialità di Hibernate

Innanzitutto Hibernate porta numerosi vantaggi rispetto al buon vecchio JDBC: lo sviluppatore infatti, non deve occuparsi della gestione della persistenza. Per persistenza dei dati si intende la mappatura tra una classe Java e un database relazionale; una volta creati il bean di riferimento per una tabella e il file di mapping XML, il programmatore non deve più preoccuparsi di questo aspetto.

Viene delegata al framework anche la gestione delle transazioni; basterà quindi invocare il metodo commit() dopo la chiamata a una query e il metodo rollback() nella gestione delle eccezioni.

Oltre ad occuparsi della persistenza, Hibernate genera le chiamate SQL e si occupa del recupero dei dati; per questo motivo, pur permettendo di scrivere direttamente query all'interno dei file di mapping, questa pratica è consigliabile solo in caso di query elaborate. Attraverso l'utilizzo delle API Criteria, Hibernate permette la chiamata a query di ricerca con un numero di condizioni variabile, senza ovviamente dover scrivere una sola riga di codice SQL.

Un paio di esempi

Di seguito sono riportati due esempi.

Abbiamo una tabella contenente libri i cui campi sono codice, titolo e autore: nel primo caso dobbiamo dobbiamo effettuare una ricerca semplice che ne restituisca tutti i record; nel secondo caso dobbiamo occuparci di una ricerca in base all'autore. Chiameremo il bean di riferimento Libro.java.

Ecco il primo esempio:

public List search(Session sess) throws Exception {
    List retval = null;
    Criteria criterio = sess.createCriteria(Libro.class);

    //ordiniamo i risultati per codice
    criterio.addOrder(Order.asc("codice"));
    try {
        retval = criterio.list();
    }
    catch (Exception e) {
        throw e;
    }
    return retval;
}

Ed ecco il secondo:

public List searchByCriteria(SearchCriteriaDTO searchCriteria, Session sess)
throws Exception {
    List retval = null;
    Criteria criteria = sess.createCriteria(Libro.class);

    //es. searchCriteria.getAutore = G.Leopardi
    if (null != searchCriteria.getAutore) {
        criteria.add(Expression.eq("autore", searchCriteria.getAutore));
    }
    try {
        retval = criteria.list();
    } catch (Exception e) {
        throw e;
    }
    return retval;
}

L'oggetto DTO viene utilizzato per trasportare i dati tra i vari strati della nostra applicazione ed è tramite questa classe quindi che abbiamo fatto arrivare al nostro metodo il valore da assegnare ad "autore" (ad esempio Leopardi).

Le relazioni fra tabelle

È possibile evitare di scrivere codice SQL anche per le query di join. Esistono diversi modi per generarne la chiamata e un utilizzo superficiale di uno di essi potrebbe far incorrere in errori che, come precedentemente accennato, potrebbero far perdere molto tempo.

È molto importante verificare sempre le relazioni esistenti tra tabelle. Potremmo effettuare il mapping di una tabella senza aver bisogno di specificare anche tali relazioni, e questo particolare potrebbe sfuggirci. In tal caso è molto probabile che il sistema lanci un'eccezione del tipo:

org.hibernate.LazyInitializationException : could not initialize proxy - no Session

Sulle API di Hibernate troviamo questa descrizione:

"public class LazyInitializationException

extends HibernateException

Indicates access to unfetched data outside of a session context. For example, when an uninitialized proxy or collection is accessed after the session was closed."

Con session ovviamente si intende la sessione propria di Hibernate (che viene aperta e richiusa ogni volta che effettuiamo una chiamata SQL).

Per risolvere il problema, basta semplicemente inserire attribuire all'attributo "lazy" del tag "class" valore false come nell'esempio:

<class name="nome_bean" table="nome_table" schema="schema" lazy="false">

Conclusioni

È senza dubbio fondamentale essere in grado di apprendere i concetti base di una tecnologia e approfondirne gli aspetti tecnici durante il lavoro di sviluppo come anche confrontarsi con chi prima di noi si è trovato ad affrontare lo stesso problema; spesso però è anche necessario documentarsi fin dall'inizio, soprattutto quando la tecnologia in questione è ampia e articolata come Hibernate, sulle potenzialità, sui vantaggi e sulle problematiche che molto probabilmente ci troveremo a dover affrontare.

Riferimenti

  • [1] C. Bauer - G. King, "Hibernate in Action", Manning Pubblications Co. 2004
  • [2] Hibernate.org

http://www.hibernate.org/