unidades:07_arquitectura:01_hibernateutil
Diferencias
Muestra las diferencias entre dos versiones de la página.
— | unidades:07_arquitectura:01_hibernateutil [2023/04/07 21:26] (actual) – creado - editor externo 127.0.0.1 | ||
---|---|---|---|
Línea 1: | Línea 1: | ||
+ | ====== HibernateUtil ====== | ||
+ | El uso de hibernate nos obliga a tener siempre disponible una referencia al objeto <javadoc h41> | ||
+ | ===== Acceso a SessionFactory ===== | ||
+ | El problema de acceder al objeto <javadoc h41> | ||
+ | |||
+ | Hay tres técnicas | ||
+ | * [[#Paso del objeto entre clases]]. | ||
+ | * [[#Objeto global]]. | ||
+ | * [[# | ||
+ | |||
+ | ==== Paso del objeto entre clases ==== | ||
+ | Esta técnica consiste en el clásico método de ir pasando el objeto SessionFactory por todos los objetos hasta llegar al que finalmente lo necesita. Es decir, que // | ||
+ | |||
+ | Esta técnica ya está en desuso y mejor usar objetos globales o [[patrones: | ||
+ | |||
+ | ==== Objeto global ==== | ||
+ | Si <javadoc h41> | ||
+ | |||
+ | Ésta es la técnica que vamos a explicar ahora ,pero posteriormente la cambiaremos por la [[patrones: | ||
+ | |||
+ | ==== Inyección de Dependencias ==== | ||
+ | La [[patrones: | ||
+ | |||
+ | En los siguientes temas seguiremos hablando sobre Inyeccion de Dependencias y Spring. | ||
+ | |||
+ | ===== HibernateUtil en NetBeans ===== | ||
+ | En cualquier libro o tutorial que hable sobre Hibernate acabará hablándose de la clase '' | ||
+ | |||
+ | Esta clase es tán //famosa// que hasta el propio NetBeans tiene una opción para crearla, si vamos a la opción de menú "File --> New File ..." y seleccionamos en el árbol " | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | El código que genera NetBeans es el siguiente: | ||
+ | |||
+ | <code java 1 | HibernateUtil creado por NetBeans> | ||
+ | public class HibernateUtil { | ||
+ | |||
+ | private static final SessionFactory sessionFactory; | ||
+ | | ||
+ | static { | ||
+ | try { | ||
+ | // Create the SessionFactory from standard (hibernate.cfg.xml) | ||
+ | // config file. | ||
+ | sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); | ||
+ | } catch (Throwable ex) { | ||
+ | // Log the exception. | ||
+ | System.err.println(" | ||
+ | throw new ExceptionInInitializerError(ex); | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | public static SessionFactory getSessionFactory() { | ||
+ | return sessionFactory; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * En las líneas 5-15 vemos un código estático que crea el objeto '' | ||
+ | * En las línea 17-19 está el método estático '' | ||
+ | |||
+ | |||
+ | ¿Por qué si es tan útil esta clase no está incluida en el propio Hibernate? Pues porque cada uno se la puede implementar según sus propias necesidades. Hemos visto la clase '' | ||
+ | * Está anticuada al usar el código de Hibernate 3 | ||
+ | * No permite pasar ningún parámetro de inicialización como por ejemplo indicar otra posible ubicación de '' | ||
+ | * No incluye código para cerrar el objeto '' | ||
+ | * No ayuda a implementar el patrón [[patrones: | ||
+ | ===== Mi versión de HibernateUtil ===== | ||
+ | Antes de mostrar la clase '' | ||
+ | |||
+ | <code java 1> | ||
+ | SessionFactory sessionFactory; | ||
+ | Session session; | ||
+ | |||
+ | |||
+ | Configuration configuration = new Configuration(); | ||
+ | configuration.configure(); | ||
+ | ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry(); | ||
+ | sessionFactory = configuration.buildSessionFactory(serviceRegistry); | ||
+ | |||
+ | session = sessionFactory.openSession(); | ||
+ | |||
+ | //Trabajar con la sesión | ||
+ | |||
+ | session.close(); | ||
+ | |||
+ | sessionFactory.close(); | ||
+ | </ | ||
+ | |||
+ | * La linea 1 es la variable donde guardaremos el objeto '' | ||
+ | * La linea 2 es la variable donde guardaremos el objeto '' | ||
+ | * Las líneas 5 a 8 crean el objeto '' | ||
+ | * La línea 10 crea el objeto '' | ||
+ | * La línea 14 cierra el objeto '' | ||
+ | * La línea 16 cierra el objeto '' | ||
+ | |||
+ | Ahora veamos el código de la clase '' | ||
+ | <code java 1 | HibernateUtil.java > | ||
+ | public class HibernateUtil { | ||
+ | |||
+ | private static SessionFactory sessionFactory; | ||
+ | |||
+ | public static synchronized void buildSessionFactory() { | ||
+ | if (sessionFactory == null) { | ||
+ | Configuration configuration = new Configuration(); | ||
+ | configuration.configure(); | ||
+ | configuration.setProperty(" | ||
+ | ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry(); | ||
+ | sessionFactory = configuration.buildSessionFactory(serviceRegistry); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | public static void openSessionAndBindToThread() { | ||
+ | Session session = sessionFactory.openSession(); | ||
+ | ThreadLocalSessionContext.bind(session); | ||
+ | } | ||
+ | |||
+ | |||
+ | public static SessionFactory getSessionFactory() { | ||
+ | if (sessionFactory==null) | ||
+ | buildSessionFactory(); | ||
+ | } | ||
+ | return sessionFactory; | ||
+ | } | ||
+ | |||
+ | public static void closeSessionAndUnbindFromThread() { | ||
+ | Session session = ThreadLocalSessionContext.unbind(sessionFactory); | ||
+ | if (session!=null) { | ||
+ | session.close(); | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | public static void closeSessionFactory() { | ||
+ | if ((sessionFactory!=null) && (sessionFactory.isClosed()==false)) { | ||
+ | sessionFactory.close(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Pasemos ahora a explicar cada una de las funciones de esta clase: | ||
+ | |||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | * '' | ||
+ | ==== ThreadLocalSessionContext ==== | ||
+ | La único que desconocemos de '' | ||
+ | |||
+ | <code java> | ||
+ | ThreadLocalSessionContext.bind(session); | ||
+ | </ | ||
+ | Guarda la sesión en la memoria privada del Thread donde se está ejecutando el código. | ||
+ | |||
+ | <code java> | ||
+ | Session session = ThreadLocalSessionContext.unbind(sessionFactory); | ||
+ | </ | ||
+ | Recupera la sesión y la borra de la memoria privada del Thread donde se está ejecutando el código. | ||
+ | |||
+ | |||
+ | Por último la línea: | ||
+ | <code java> | ||
+ | configuration.setProperty(" | ||
+ | </ | ||
+ | Configura la clase <javadoc h41> | ||
+ | |||
+ | |||
+ | Ahora bien, ¿para que queremos guardar un objeto '' | ||
+ | |||
+ | Todo ésto se está haciendo para que '' | ||
+ | |||
+ | En una aplicación web habrá a la vez muchos objetos '' | ||
+ | |||
+ | Así que lo que queremos crear es un objeto '' | ||
+ | |||
+ | Lo que nos falta por explicar es como recuperamos la sesión guardada en la zona de memoria provada del Thread.Mediante el codigo siguiente: | ||
+ | <code java> | ||
+ | Session session=HibernateUtil.getSessionFactory().getCurrentSession(); | ||
+ | </ | ||
+ | El quid de la cuestión es que esta línea obtendrá una sesión distinta en cada petición/ | ||
+ | |||
+ | |||
+ | Recopilando , el método '' | ||
+ | <code java> | ||
+ | Session session=HibernateUtil.getSessionFactory().getCurrentSession(); | ||
+ | </ | ||
+ | Obtengamos siempre la sesión asociada a nuestra petición/ | ||
+ | |||
+ | Es decir que hemos creado un '' | ||
+ | |||
+ | ==== getCurrentSession() ==== | ||
+ | Volvamos otra vez sobre el método <javadoc h41> | ||
+ | |||
+ | Hasta ahora para obtener un objeto '' | ||
+ | |||
+ | ¿Qué diferencia hay entre ellos? | ||
+ | |||
+ | El método '' | ||
+ | |||
+ | |||
+ | |||
+ | ===== Main ===== | ||
+ | Veamos ahora cómo inicialmente queda la clase '' | ||
+ | |||
+ | <note tip> | ||
+ | El uso de esta clase en una aplicación web se ve en [[unidades: | ||
+ | </ | ||
+ | |||
+ | <code java 1> | ||
+ | public class Main { | ||
+ | |||
+ | public static void main(String[] args) { | ||
+ | HibernateUtil.buildSessionFactory(); | ||
+ | |||
+ | try { | ||
+ | HibernateUtil.openSessionAndBindToThread(); | ||
+ | |||
+ | Session session = HibernateUtil.getSessionFactory().getCurrentSession(); | ||
+ | Profesor profesor = (Profesor) session.get(Profesor.class, | ||
+ | System.out.println(profesor.toString()); | ||
+ | } finally { | ||
+ | HibernateUtil.closeSessionAndUnbindFromThread(); | ||
+ | } | ||
+ | |||
+ | HibernateUtil.closeSessionFactory(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Como podemos ver, ha quedado todo muy sencillo ya que seguimos los 5 pasos que necesitamos en Hibernate: | ||
+ | * Línea 4: Inicializamos Hibernate. | ||
+ | * Línea 7: Creamos la sesión y la enlazamos al thread actual | ||
+ | * Línea 9: Obtenemos la sesión. | ||
+ | | ||
+ | * Línea 13: Cerramos la sesión. | ||
+ | * Línea 16: Cerramos Hibernate. | ||
+ | |||
+ | La única peculiaridad son las líneas 6 y 12 con el '' | ||
+ | |||
+ | <note tip> | ||
+ | También nos faltaría garantizar que se cierre Hibernate mediante la llamada a '' | ||
+ | </ |