Hibernate: Ottenere la Session

Hibernate: Come inizializzare una Session
G.Morreale

Introduzione:

Dovendo fare diversi esprimenti utilizzando hibernate, mi sono trovato davanti all'inizializzazione dell'oggetto Session di hibernate al fine di utilizzarlo al posto dell'EntityManager.

Il Codice

Passiamo direttamente a vedere il codice che commenterò di seguito passo per passo.

        AnnotationConfiguration configuration = new AnnotationConfiguration();
        configuration.addResource("META-INF/hibernate.cfg.xml");
        configuration.addPackage("entities");        
        configuration.addAnnotatedClass(entities.Esempiotable.class);       
        configuration.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");        
        configuration.setProperty("hibernate.connection.datasource", "esempioJNDI");        
        SessionFactory sf = configuration.buildSessionFactory();        
        Session ses = sf.openSession();   

La prima riga di codice serve a inizializzare la Configuration.

AnnotationConfiguration configuration = new AnnotationConfiguration();

Essa è la rappresentazione della configurazione di hibernate.
Tale configurazione spesso viene inserita all'interno di un file xml, per cui non appena inizializzato l'oggetto lo si può aggiornare con i settaggi presenti nel file xml di configurazione

configuration.addResource("META-INF/hibernate.cfg.xml");

Il metodo addResource è utilizzato quando il file di configurazione si trova nel classpath (ad es. dentro il jar)

Ma torniamo alla prima riga di codice: Perchè AnnotationConfiguration piuttosto che Configuration?
La scelta di questa specializzazione della classe è dovuta al mapping.
Hibernate è un ORM framework, quindi deve conoscere il mapping tra i dati relazionali (le tabelle ad esempio) e i corrispettivi entity.
Tale mapping può essere configurato in diversi modi

  • file xml di configurazione
  • settando le oppurtune proprietà sull'istanza di configuration
  • Attraverso le annotation

Se il progetto, come nel caso dell'esempio, ha un mapping effettuato attraverso annotation, si può aggiornare la configuration indicando il nome del package e/o della classe che ha le annotazioni che provvedono al mapping.

Istruzioni per indicare a hibernate dove trovare il mapping dell'Entity Esempiotable
configuration.addPackage("entities");        
configuration.addAnnotatedClass(entities.Esempiotable.class);

nota:
Nel caso in cui il mapping non è configurato si ottiene il seguente errore nello stack trace:
.... Caused by: org.hibernate.MappingException: ....

andiamo avanti:
Il dialect, se tale proprietà non viene settata hibernate genera un eccezione

..HibernateException: Hibernate Dialect must be explicitly set..

Ovviamente tale settaggio, come tutti gli altri, può essere inserito all'interno del file xml.

Se non si setta opportunamente il datasource si ottiene il seguente errore:

....The user must supply a JDBC connection.....

Quindi bisogna fornire a hibernate indicazioni circa le connessioni jdbc.
Esse di solito vengono settate attraverso le seguenti proprietà dal chiaro significato.

  • hibernate.connection.driver_class
  • hibernate.connection.url
  • hibernate.connection.username
  • hibernate.connection.password

etc. etc.

Ma nel caso, come l'esempio, in cui si vuole utilizzare una risorsa (JNDI) dell'application pool è possibile settare il JNDI name (e altre proprietà opzionali) per indicare a hibernate di estrarre la connessione attraverso la risorsa del container.
L'istruzione per far ciò è la seguente.
       
configuration.setProperty("hibernate.connection.datasource", "esempioJNDI");
        
Le ultime due istruzioni sono banali, esse servono una a creare una SessionFactory, ovvero un oggetto thread-safe in grado di generare session l'altra invece serve a generare una sessione, una unit of work, un'oggetto NON thread safe in grado di rappresentare la conversazione con il persistence context e il db.

        SessionFactory sf = configuration.buildSessionFactory();        
        Session ses = sf.openSession();   

Una volta ottenuto l'oggetto session si possono eseguire query, operazioni di find, merging, save etc. date un occhio alla javadoc di hibernate: http://www.hibernate.org/hib_docs/v3/api/org/hibernate/Session.html


Conclusione

Al fine di creare del codice il più ordinato possibile la configurazione dovrebbe risidiere nel file xml opportunamente costruito secondo le specifiche di hibernate.
Nonostante ciò ho voluto mostrare come creare una session aggiungendo alcune proprietà mancanti sull'istanza della configurazione.
Inoltre le proprietà mancanti non sono necessarie nel caso in cui si usa l'entityManager piuttosto che l'oggetto session.

5 comments:

megahal said...

io mi ritrovo col problema inverso, come faccio ad ottenere i la configurazione usata (in particolare il nome dell'host) senza dover leggere dal file di configurazione?

Giuseppe Morreale said...

cosa intendi per nome dell'host?
l'host dove si trova il db?
l'host del client?
o altro?

megahal said...

Io ho una connessione funzionante, voglio ottenere i dati di questa connessione. per poter istanziare una mia classe che fa il backup di un database mysql, la mia classe non usa hibernate

Giuseppe Morreale said...

Deve ottenere un oggetto
org.hibernate.cfg.Configuration, da lì attraverso il metodo getProperty può accedere a tutte le proprietà della configurazione tra cui il jdbc url contenente l'host del dbms.

Se hai una session sicuramente da qualche parte l'hai inizializzata usando una configurazione.devi usare quella!

megahal said...

Ottimo! grazie del consiglio, ho risolto.

(la sessione era generata da netbeans quindi l'ogetto con la configurazione era stato reso privato)