Manejar dos bases de datos distintas con Hibernate

0
47626

Como manejar dos bases de datos distintas con Hibernate

Índice de contenidos

1. Introducción

2. Entorno

3. Hibernate con más de una base de datos

4. Probando la clase de ayuda

5. Conclusiones

1. Introducción

En ciertas ocasiones nos vemos obligados a manejar en una aplicación más de una base de datos diferente.

En este tutorial vamos a exponer una clase de ayuda para poder gestionar esta situación con Hibernate.

2. Entorno

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil Ahtex Signal X-9500M (Centrino 1.6 GHz, 1024 MB RAM, 60 GB HD).
  • Sistema Operativo: GNU / Linux, Debian Sid (unstable), Kernel 2.6.11, KDE 3.4
  • Máquina Virtual Java: JDK 1.5.0_03 de Sun Microsystems
  • Hibernate 3.0 (http://www.hibernate.org)

3. Hibernate con más de una base de datos

En principio no hay ningún problema para poder gestionar mas de una base de datos con Hibernate.

En Hibernate podemos tener mas de un fichero de configuración, siendo el fichero de configuración por defecto “hibernate.cfg.xml”. Cada fichero de configuración puede representar una conexión a una base de datos distinta, y por supuesto cada fichero de configuración hará referencia a los ficheros de mapeo correspondientes para las tablas de cada base de datos.

La clase que vamos a presentar a continuación pretende facilitar la gestión de está situación, consiguiendo de forma sencilla sesiones de Hibernate a cada una de las bases de datos.

Además la clase se encarga de asegurar que la sesión de Hibernate es única por Thread. Esto puede resultar muy conveniente en aplicaciones multithread o en aplicaciones Web donde múltiples clientes acceden de forma simultánea.

El código de la clase es el siguiente:

package com.autentia.tool; import java.util.HashMap; import java.util.Map; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; /**  * Clase de utilidad para conseguir la sesión de Hibernate.  * La sesión es única por thread.  * Pueden existir varios ficheros de configuración.  * Al menos siempre existirá la configuración por defecto sacada del fichero "hibernate.cfg.xml".  *   * @author Autentia  */ public class HibernateMultipleConfig {     /** Clave para acceder a la sesión por defecto, esta sesión se obtiene a partir del fichero de configuración "hibernate.cfg.xml". */     public static final String DEFAULT = "default";     /** Mapa donde se guardan los SessionFactory para cada uno de los ficheros de configuración. */     private static final Map<String, SessionFactory> sessionFactorys = new HashMap();     /** Atributo único por threat donde se guardan las sesiones para cada uno de los ficheros de configuración. */     private static final ThreadLocal<Map<String, Session>> sessions = new ThreadLocal>();     static {         try {             // Create the DEFAULT SessionFactory from hibernate.cfg.xml             SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();             sessionFactorys.put(DEFAULT, sessionFactory);         } catch (Throwable e) {             // Make sure you log the exception, as it might be swallowed             System.err.println("Initial SessionFactory creation failed." + e);             throw new ExceptionInInitializerError(e);         }         // Creamos el mapa donde se guardará la sesión para cada una de las configuraciones.         // Este mapa lo guardamos en el atributo sessions, que nos asegura que el mapa es único por thread.         sessions.set(new HashMap<String, Session>());     }     /**      * Añade un nuevo fichero de configuración, creando el SessionFactory correspondiente.      * Para encontrar el fichero de configuración, este debe encontrarse en el classpath,      * junto al fichero de configuración por defecto de hibernate "hibernate.cfg.xml".       *       * @param fileName nombre del fichero de configuración que se quiere añadir.      * @param key clave con la que se hará referencia a esta configuración en las siguientes llamadas.      * @throws HibernateException si no se puede crear el SessionFactory basado en el fichero que se pasa como      *             argumento.      */     public static void addConfigFile(String fileName, String key) throws HibernateException {         SessionFactory sessionFactory = new Configuration().configure(fileName).buildSessionFactory();         sessionFactorys.put(key, sessionFactory);     }     /**      * Devuelve la sesión, para el thread que hace la llamada. Es decir cada thread tiene su propia sesión.      *       * @param key clave que identifica la sesión a la que se quiere acceder.      * @return sesión por defecto, para el thread que hace la llamada.      * @throws HibernateException      */     public static Session currentSession(String key) throws HibernateException {         Map<String, Session> ss = sessions.get();         Session s = ss.get(key);         // Abre una nueva sesión si este thread todavía no tiene ninguna         if (s == null) {             s = sessionFactorys.get(key).openSession();             ss.put(key, s);         }         return s;     }     /**      * Cierra la sesión, para el thread que hace la llamada.      *       * @param key clave que identifica la sesión que se quiere cerrar.      * @throws HibernateException      */     public static void closeSession(String key) throws HibernateException {         Map<String, Session> ss = sessions.get();         Session s = ss.get(key);         if (s != null) {             s.close();             ss.put(key, null);         }     }     /**      * Devuelve la sesión por defecto, para el thread que hace la llamada.      * Es decir cada thread tiene su propia sesión.      *       * @return sesión por defecto, para el thread que hace la llamada.      * @throws HibernateException      */     public static Session currentSession() throws HibernateException {         return currentSession(DEFAULT);     }     /**      * Cierra la sesión por defecto, para el thread que hace la llamada.      *       * @throws HibernateException      */     public static void closeSession() throws HibernateException {         closeSession(DEFAULT);     } }

Este código está basado en la clase de ayuda propuesta por la documentación de Hibernate en:
http://www.hibernate.org/hib_docs/v3/reference/en/html/tutorial.html#tutorial-firstapp-helpers

4. Probando la clase de ayuda

Aquí proponemos un pequeño ejemplo para probar la clase de ayuda:

import org.hibernate.Session; import com.autentia.tool.HibernateMultipleConfig; public class TestHibernateMultipleConfig {     public static void main(String[] args) {         // Añadimos un nuevo fichero de configuración,         // a parte de la configuración por defecto obtenida del fichero "hibernate.cfg.xml".         // Primero indico el nombre del fichero de configuración,         // y luego la clave por la que haré referencia a esa configuración.         // Esto sólo habría que hacerlo una vez, en una fase de inicialización de la aplicación.         HibernateMultipleConfig.addConfigFile("miOtraConfiguracion.hibernate.cfg.xml", "otraConfiguracion");                                                            // Trabajamos con la sesión por defecto de hibernate.         // La sesión por defecto se obtiene del fichero "hibernate.cfg.xml".         Session defaultSession = HibernateMultipleConfig.currentSession();         // ...                          HibernateMultipleConfig.closeSession();                                                                             // Trabajamos con una sesión concreta de hibernate.         // La sesión se obtendrá a partir de la clave que se pasa como parámetro.         Session aSession = HibernateMultipleConfig.currentSession("otraConfiguracion");                          // ...                       HibernateMultipleConfig.closeSession("otraConfiguracion");     } }

5. Conclusiones

Esta clase no pretende ser perfecta ni la solución definitiva (si encontráis algún bug decírmelo ;), pero si pretende ser un buen punto de partida para la gestión de múltiples bases de datos con Hibernate.

Seguramente un buen punto a mejorar es como se cierran las sesiones. Habría que intentar facilitar un poco más la vida al desarrollador, de forma que pudiera hacer algo como “aSession.close()” y ya se realizara toda la gestión (os lo dejo como deberes). En cualquier caso no os olvidéis nunca de cerrar las sesiones (y en general de cerrar cualquier recurso: conexiones, streams, …).

Espero que os sirva de ayuda, y nos vemos en el próximo tutorial.

 

Alejandro Pérez García
Alejandro es socio fundador de Autentia y nuestro experto en Java EE, Linux y optimización de aplicaciones empresariales. Ingeniero en Informática y Certified ScrumMaster. Seguir @alejandropgarci Si te gusta lo que ves, puedes contratarle para darte ayuda con soporte experto, impartir cursos presenciales en tu empresa o para que realicemos tus proyectos como factoría (Madrid). Puedes encontrarme en Autentia: Ofrecemos servicios de soporte a desarrollo, factoría y formación.

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad