Omet navegació

5.5 - SessionFactory únic: Singleton

En la pregunta 4 havíem comentat que si només accedíem a una Base de Dades, havíem de crear només un SessionFactory, i a través d'ell crear-nos totes les sessions que ens facen falta.

Per a assegurar-nos que només creem un objecte de SessionFactory anem a utilitzar la tècnica del Singleton. És una tècnica utilitzada en programació quan volem assegurar-nos que només instanciem un objecte d'una classe. Consistirà en crear una classe diferent que és la que crearà la instància de l'objecte. La primera vegada que es cride a aquesta classe crearà l'objecte, i quan ja estiga creat senzillament tornarà una referència a l'objecte creat.

Aprofitarem també per a arreglar el deprecated que teníem en el buildSessionFactory. El mètode que no està deprecated és buildSessionFactory(ServiceRegistry)

I també aprofitem per a que no coste tant la connexió. La raó de tardar tant és perquè per defecte vol carregar les metadades de la Base de Dades. Però en PostgreSQL en principi es poden veure totes les altres Bases de Dades que hi ha al servidor, encara que després no puguem connectar. Però igual vol carregar les metadades i tarda molt en intentar (i no poder) connectar. La manera de solucionar-ho serà dir-li que no carregue les metadades. Ho aconseguirem amb la sentència:

            conf.setProperty("hibernate.temp.use_jdbc_metadata_defaults","false");

Ací tenim la classe que ens ajudarà a fer el singleton. L'anomenarem SessioFactoryUtil, i el podem col·locar també en el paquet classes:

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
 
public class SessionFactoryUtil {
 
    private static SessionFactory sF;
 
    public static SessionFactory getSessionFactory() {
        if (sF == null) {
            Configuration conf = new Configuration().configure();
            conf.setProperty("hibernate.temp.use_jdbc_metadata_defaults","false");
            ServiceRegistryBuilder reg = new ServiceRegistryBuilder();
            reg.applySettings(conf.getProperties());
            ServiceRegistry serviceRegistry = reg.buildServiceRegistry();
             
            sF = conf.buildSessionFactory(serviceRegistry);           
        }
         
        return sF;
    }
}

Des de fora sempre cridarem a getSessionFactory (i ens assegurem perquè l'objecte és privat). La primera vegada, com és nul, el crearà. Però les següents vegades únicament tornarà la referència a l'objecte ja creat. A continuació mostrem el mateix exemple de l'apartat anterior, però ara utilitzant el Singleton:

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import classes.Comarca;
import classes.SessionFactoryUtil;
 
public class SegonAcces {
 
public static void main(String[] args) {
 
        SessionFactory sf = SessionFactoryUtil.getSessionFactory();
        Session sessio = sf.openSession();
        Comarca com = (Comarca) sessio.load(Comarca.class, "Alt Maestrat");
        System.out.print("Comarca " + com.getNomC() + ": ");
        System.out.print(com.getProvincia());
        System.out.println(" (" + com.getPoblacios().size() + " pobles)");
        sessio.close();
    }
}