Mostrando entradas con la etiqueta Hibernate. Mostrar todas las entradas
Mostrando entradas con la etiqueta Hibernate. Mostrar todas las entradas

domingo, 3 de mayo de 2020

Como usar c3p0 en JPA Hibernate

Cuando damos nuestros primeros pasos en JPA/Hibernate no nos preocupan los detalles, solo queremos ver lo fácil y rápido que es poder persistir objetos en nuestra base de datos. Realizar consultas y otros temas relacionados con la persistencia de datos.

Cierto día mi servidor de Base de datos MySQL estaba apagado, mi aplicación se demoró unos 5 minutos en intentar establecer conexión. Dejando la aplicación congelada durante ese tiempo. Este fue el motivo que me llevó a investigar como tener mayor control con la conexión a la base datos, me llevó a preguntarme como establecer un time-out.
El otro motivo fue el log que me llamó la atención, el mensaje decía "using hibernate built-in connection pool (not for production use )". Esto significa que Hibernate viene con un pool de conexiones integrado, un pool de conexiones que no está recomendado para ser usado en producción, solo para desarrollo.

C3P0 es un pool de conexiones de base de datos, tu puedes establecer un rango de conexiones permitidos, estás conexiones se van instanciando a demanda. Por ejemplo, al iniciar tu aplicación es posible que se instancie una primera conexión, si tu sistema es multi-hilo posiblemente estás cargando los datos de configuración mientras el usuario necesita hacer login, el pool de conexiones se da cuenta de que necesitas una conexión más, primero buscará una conexión ya instanciada pero que este sin usar, de existir te entregará esa conexión, si no existe entonces va a crear una nueva instancia.

C3P0 no solo es un pool de conexiones, tiene muchas otras características, una de ellas es poder establecer un timeOut de conexión, un timeOut de consulta entre otras características.

Voy a explicar como integrar y usar C3P0 en proyecto Maven y en un proyecto Java estándar.

Integrar C3P0 en un proyecto Maven

Lo que debemos hacer es agregar la dependencia en nuestro archivo pom.xml

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-c3p0</artifactId>
    <version>5.3.6.Final</version>
</dependency>

La versión debe ser similar o lo más cercano a la versión de hibernate-entitymanager, la ventaja de usar Maven es que automáticamente va identificar si hibernate-c3p0 requiere de otras dependencias y así recursivamente, por eso, si vas a la lista de dependencias de tu proyecto, vas a notar que ahora tienes las siguientes dependencias.

hibernate-c3p0-5.3.6.Final.jar
c3p0-0.9.5.2.jar
mchange-commons-java-0.2.11.jar

Si te preguntas como me he enterado de todos los jars necesarios, pues te diré que en el repositorio de maven está la lista de todas las dependencias. Tu buscas hibernate-c3p0-5.3.6.Final.jar y se te mostrará las dependencias necesarias para compilar y/o ejecutar.

Integrar C3P0 en un proyecto estándar

Para integrar c3p0 en un proyecto estándar debes descargar los jars por separados, los puedes descargar desde el repositorio de maven. Una vez descargados debes agregarlos al classpath de tu proyecto.

Propiedades C3P0
Las propiedades más relevantes para c3p0 son:

hibernate.c3p0.min_size: El numero minimo de conexiónes a mantener en el pool de conexiones. Conexiones que si no se usan estarán "dormidas"
hibernate.c3p0.max_size: El numero maximo de conexiones a mantener en el pool de conexiones. Si se llega al numero máximo de conexiones y la aplicación requiere más conexiones entonces la petición quedará bloqueada hasta que una conexion esté disponible.
hibernate.c3p0.checkoutTimeout= El timeout en mili segundos para establecer la conexion con la base de datos. Si no se estable a conexion en ese timeout se lanzará una excepción.

Estás propiedades se agregan en la unidad de persistencia, dentro del archivo persistence.xml o también se pueden agregar mediante código fuente.

domingo, 10 de febrero de 2019

Errores Comunes con JPA

En los últimos meses he estado depurando una aplicación Swing que hace uso de JPA para la persistencia de datos. La integración presenta múltiples violaciones a las reglas de uso impactando en el rendimiento y confiabilidad de la aplicación.
En esta entrada voy a compartirles algunos errores muy comunes en el uso de JPA, conocerlos te ayudará a ser un mejor Ingeniero de Desarrollo de Software, creando aplicaciones de calidad, que siempre estén disponibles, haciendo más felices a los usuarios finales.

El ciclo de Vida de un EntityManager

Debes tener muy claro cual será el ciclo de vida de un EntityManager, recuerda que un EntityManager tiene asociado una cache (JPA First Cache). Un EntityManager es un objeto ligero, crear instancias no consumen mucho recurso, así que puedes crear tantas instancias de EntityManager requieras.
Una vez que termines de usar tu instancia EntityManager debes de cerrarlo explicita mente llamando al método close. No hacerlo puede dejar conexiones abiertas y no liberar la memoria ocupada por el cache. Algunos servidores tienen un máximo de conexiones permitido, al alcanzarlo el servidor se puede bloquear.
En cuanto a la cache, la aplicación se puede quedar sin memoria disponible causando una excepción del tipo Java Heap Space, cerrar el EntityManager libera el espacio ocupado por el cache.
No hay una regla especifica para decir el ciclo de vida de un EntityManager, pero ten presente la cache asociada y cerrar el EntityManager una vez que decidas terminar el ciclo de vida.
En una aplicación Web es un poco distinto porque es el contenedor Web quien gestiona el ciclo de vida de forma automática, el decide cuando crearlos y cuando cerrarlos.

Continuará...

jueves, 8 de septiembre de 2016

Hibernate ORM Introducción

Introducción
Toda aplicación llega un momento en el que tiene que recolectar, procesar, transformar y guardar
una cantidad considerable de datos, se guarda en algún lugar y que perdure con el tiempo.
En el mundo Java se ha hecho un gran esfuerzo por simplificar y reducir el tiempo del proceso de desarrollo en la lectura y escritura de datos entre una aplicación y una base de datos.
Primero surgió la tecnología JDBC y últimamente la tecnología JPA, antes de adentrarnos a lo que es JPA debemos conocer el concepto ORM e Hibernate.

¿Qué es persistencia?
Como mencioné al inicio, casi todas las aplicaciones requieren datos persistentes(que duren en el tiempo) . La persistencia es un concepto fundamental en el desarrollo de aplicaciones. Si un sistema de información no permite conservar los datos cuando este se cierra o cuando el computador se apaga, entonces el sistema sería de poca utilidad práctica .
Cuando hablamos acerca de la persistencia en Java, normalmente estamos hablando de almacenamiento de datos en una base de datos relacional utilizando SQL, no necesariamente pero si en su mayoría, ya que igual podemos persistir datos en archivos xml o archivos planos.

Bases de datos relacionales
Las bases de datos nacieron hace muchos años como un medio o tecnología para almacenar datos, con el tiempo han evolucionado y hoy suenan otras tecnologías cómo: almacenamiento en la nube, Big Data y NoSQL.
Pero aun así las bases de datos relacionales siguen siendo las más usadas, ya que son de propósitos generales.
No sé con certeza que porcentaje de las aplicaciones Java usen base de datos relacionales como tecnología de almacenamiento de datos, pero al menos en mi vida laboral, siempre las hemos usado. En la web puedes encontrar información más extensa sobre base de datos relacionales.

ORM Object-Relational Mapping (Mapeo Objeto Relacional)
En Java tenemos como nuestro elemento básico una clase, el cual tiene un conjunto de atributos(variables de instancia de la clase) y cada atributo un tipo de dato. La base de datos relacional tiene una tabla con un conjunto de columnas y cada columna un tipo de dato. Se ven bastante similares. Debe ser simple para convertir una a la otra de forma automática. Este es un pensamiento que probablemente todos hemos tenido en un momento u otro mientras escribimos un DAO(Objeto de Acceso a Datos) para convertir los resultados de una consulta JDBC (Java Database Connectivity)  en algo orientado a objetos. El modelo de clases parece bastante similar al modelo relacional de la base de datos que parece pedir una forma de hacer que los dos modelos se comuniquen entre sí.

En pocas palabras, el  mapeo objeto-relacional es la persistencia de objetos de una aplicación Java a las tablas de una base de datos relacional de forma automatizada (y transparente), utilizando metadatos que describe la correlación entre los objetos y la base de datos .
ORM, en esencia, transformar datos de una representación a otra y viceverza. es decir de objetos a tablas y de tablas a objetos. Este proceso implica ciertas penalizaciones de rendimiento que por ahora ignoraremos.

Una solución ORM consta de las siguientes cuatro piezas :
  1. Una API para realizar operaciones básicas CRUD sobre los objetos de las clases persistentes
  2. Un lenguaje o API para especificar consultas que se refieren a las clases y sus atributos.
  3. Una instalación para especificar metadatos de mapeo
  4. Una técnica para la aplicación ORM para interactuar con objetos transaccionales y para llevar a cabo la ejecución de los objetos manipulados, carga de datos a demanda, y otras funciones de optimización

Antes de entrar en los detalles de mapeo objeto-relacional, vamos a definir un breve manifiesto de lo que la solución ideal debe ser.

• Objetos, no tablas: Las aplicaciones deben ser escritas en términos del modelo de objetos, sin estar ligado al modelo relacional. Debería ser posible operar sobre el modelo de objetos sin tener que expresarlo en el lenguaje relacional de tablas, columnas, y las claves externas.

• Comodidad, no ignorancia: Las herramientas de mapeo deben ser utilizadas sólo por personas con amplia experiencia en la tecnología relacional. ORM no está destinado a ser una solución para aquellos desarrolladores novatos que no tienen idea de la tecnología relacionales.  Está dirigido para aquellos que tienen una comprensión de los problemas que enfrentan y saben lo que necesitan, pero que no quieren tener que escribir miles de líneas de código para hacer frente a un problema que ya ha sido resuelto.

• Discreto, no es transparente: Es razonable esperar que la persistencia sea transparente
porque una aplicación siempre necesita tener el control de los objetos que persiste y
ser consciente del ciclo de vida de la entidad. La solución de ORM no debe entrometerse en el dominio del negocio, es más, las clases del  dominio del negocio no están obligados a extender clases o implementar interfaces que imponga la solución ORM.

• Base de datos ya existente, nuevos objetos: Es mucho más probable que una aplicación se integrará a una base de datos ya existente que a una base de datos nueva. El soporte a base de datos ya existentes (Legacy) es un caso muy común al que nos enfrentaremos y una buena herramienta ORM está preparado para ello.

• Suficiente, pero no demasiado: Los desarrolladores de aplicaciones tienen problemas que resolver, y que necesitan características suficientes para resolver esos problemas. No necesitamos un ORM muy poderoso pero a la vez complicado de usar, si no, luego sale más caro el remedio que el problema.

• Local, pero móvil: Una representación persistente de datos no necesita ser modelado como un conjunto de objetos totalmente remoto. La distribución es algo que existe como parte de la aplicación, no como parte de la capa de persistencia. Las entidades(objetos) que son persistentes, sin embargo, deben ser capaz de viajar con cualquier capa que necesite estar en una aplicación distribuida.

• API estándar, con implementaciones compatibles: Las grandes empresas con aplicaciones de tamaño considerable no quieren arriesgarse a estar amarrados a bibliotecas e interfaces específicas de un producto. Ellos quieren depender de interfaces estándares y bien definidos, que su aplicación esté desacoplada de APIs propietarios y cambiar fácilmente a otro producto o solución ORM si esté es más adecuado.
Esto parece ser un poco exigente, pero la practica y la experiencia han demostrado que no es un capricho, es una necesidad. Las aplicaciones empresariales tienen necesidades muy específicas de persistencia.

¿Por qué usar ORM?
Una implementación ORM es compleja, no tan compleja como la implementación de un servidor, pero más complejo que un framework de aplicaciones web como Struts o Tapestry.
¿Entonces, por qué debemos introducir otro elemento de infraestructura compleja en nuestro sistema? ¿Valdrá la pena? Según mi experiencia, una vez superada la curva de aprendizaje, si vale la pena y mucho, déjame darte unas cuantas razones.

Primero un mito, una supuesta ventaja de un ORM es que no necesitas usar sentencias SQL, es así de transparente, solo manipulas objetos. Para mi, es un mito, ya que en la realidad he tenido que usar SQL, pero muy poco. Aun así es aconsejable tener una amplia experiencia y nivel suficiente de familiaridad con el lenguaje SQL y el modelo de datos relacional, con el fin de trabajar mas facilmente con ORM. Ahora sí, vamos a ver algunos de los beneficios de la ORM e Hibernate.
Productividad
El código relacionado con la persistencia puede ser tal vez el código más tedioso en una aplicación Java, claro, usando JDB.
Hibernate elimina gran parte del trabajo pesado (más de lo que era de esperar) y le permite concentrarse en el problema de negocio.
No importa qué estrategia de desarrollo de aplicaciones prefieras usar, ya sea que primero diseñes tu modelo relacional o tu modelo de objetos, Hibernate te ayudará a reducir el tiempo de desarrollo.
Mantenibilidad
Menos líneas de código hacen que el sistema sea más comprensible, porque se enfoca en la lógica de negocio. Lo más importante, un sistema con menos código es más fácil de refactorizar. Automáticamente el mapeo objeto-relacional sustancialmente reduce las lineas de codigo.
Sin embargo, hay otras razones por las que una aplicación de Hibernate es más fácil de mantener. En los sistemas con persistencia codificado a mano, existe una tensión inevitable entre la representación relacional y el modelo de objetos de la aplicación del negocio. Los cambios en uno casi siempre implican cambios en el otro, y a menudo el diseño de una representación se ve comprometida para dar cabida a la existencia del otro. (Lo que casi siempre ocurre en la práctica es que el modelo de objetos del negocio se vea comprometida.) ORM proporciona un amortiguador entre los dos modelos, lo que permite un uso más elegante de la programación orientación a objetos en el lado de Java.
Rendimiento
La persistencia codificado a mano siempre puede ser más eficiente, y a menudo puede ser más rápido que la persistencia automatizada. Esto es cierto en el mismo sentido que es cierto que el código ensamblador siempre puede ser al menos más rápido que el código de Java, o un analizador escrito a mano siempre puede ser al menos más rápido que un analizador sintáctico generado por YACC o Antlr. Sin embargo, poner en balanza el tiempo enorme que nos toma en codificar contra el tiempo despreciable que perdemos en rendimiento del código automatizado, creo que es justificable, además, las personas que implementan el software ORM probablemente tenían mucho más tiempo para investigar optimizaciones de rendimiento de lo que nosotros tenemos. 
La independencia del proveedor
Un ORM abstrae su aplicación de la base de datos Relacional y del lenguaje SQL. Si la herramienta es compatible con un número de diferentes bases de datos (y la mayoría lo hace), esto confiere un cierto nivel de portabilidad de la aplicación. Aunque en la realidad no es llegar y cambiar de implementación así por así, se requiere un poco de trabajo para manejar las particularidades de cada implementación para no perder la potencia que ofrece cada una. Sin embargo, por lo general es mucho más fácil desarrollar una aplicación multiplataforma utilizando ORM, incluso si no requieres la capacidad multiplataforma, un ORM todavía puede ayudar a mitigar algunos de los riesgos asociados con el proveedor. Además, la independencia de base de datos ayuda en escenarios de desarrollo donde los desarrolladores utilizan una base de datos local light, pero en producción utilizan una base de datos distinta.

Hibernate es ORM bastante maduro, potente y hasta cierto punto fácil de usar, me ha sorprendido como ha evolucionado, en sus primeras versiones era muy tedioso trabajar con el, pero en las últimas el trabajo se ha simplificado muchísimo. Yo lo usé en sus primeras versiones para luego desesperarme y dejarlo en el olvido, lo retomé en el 2014 cuando ya estaba muy maduro,y así hoy lo uso en cada requerimiento de persistencia de datos.

Referencia
Christian Bauer and Gavin King. (2006). Java Persistence with Hibernate. United States of America: Manning.

Mike Keith, Jason Cranford Teague. (2013). Pro JPA 2. Estados Unidos: Apress.