viernes, 3 de agosto de 2012

JodaTime y como integrarlo con Hibernate

Java
Las clases proporcionadas en la API de Java para trabajar con fechas tienen varios defectos. JodaTime es una librería alternativa a las clases del JDK que trata de arreglarlos o no tenerlos, sus características son las siguientes:
    Hibernate
  • Fácil de usar: dispone de métodos para acceder de forma sencilla al año o al día del año entre otros.
  • Más fácil de exterder: se le pueden añadir nuevos calendarios de forma más sencilla que la necesaria en la API de Java.
  • Conjunto de características completo: proporciona mayor funcionalidad para el cálculo de fechas.
  • Interoperabilidad sencilla: es fácil de realizar conversiones entre el JDK y JodaTime.
  • Mejor rendimiento: solo realiza las operaciones minimas necesarias.
  • Documentación completa: tiene una guía de usuario y una API en javadoc
  • Madurez: está ampliamente probada desde su inicio de desarrollo en el 2002.
  • Código abierto: tiene una licencia Apache.
Aparte de estas características una de las más destacadas es que facilita la automatización de casos de pruebas que dependan de fechas ya que podemos establecer que la fecha altual de joda time sea una que esté en el pasado o en el futuro de forma sencilla (esto es haciendo new JodaTime() en vez de tener la fecha del sistema podemos hacer que la fecha sea la que queramos). Solo por esto ya merece la pena usarla aunque hay otras razones. Además de poder representar fechas con JodaTime pueden ser representados otros conceptos:
  • Instante: Representa un instante en el tiempo medido en milisegundos transcurridos desde el 1970-01-01T00:00Z.
  • Parcial: Un parcial no contiene contiene todos los campos pero añadiendoselos se puede obtener un instante (parcial + campos faltantes + zona horaria = instante).
  • Intervalo: Representa el periodo de tiempo de un instante a otro instante.
  • Duracion: Representa una duración de tiempo medido en milisegundos, instante + duracion = instante.
  • Periodo: Representa un perido de tiempo medido en terminos de campos como años, meses, días u horas. Un periodo de tiempo puede ser inexacto en términos de tiempo ya que tiene en cuenta cosas como los años bisiestos o los cambios de hora.
Además puede se integrada perfectamente con Hibernate de tal forma que en nuestras entidades de dominio podamos tener por ejemplo propiedades del tipo DateTime entre otras, evintandonos conversiones entre nuestro modelo y la representación con la que realizamos los cálculos y operaciones. Lo primero que deberemos hacer para tener esta integración entre Hibernate y JodaTime es incluir la propia librería de JodaTime y el soporte para Hibernate como dependencias a nuestro proyecto. Son las siguientes:
  • joda-time:joda-time:2.1
  • joda-time:joda-time-hibernate:1.3
La librería joda-time-hibernate proporciona soporte para la versión 3.6 de hibernate, si usamos hibernate 4 deberemos usar usertype:
  • org.jadira.usertype:usertype.parent:3.0.0.CR1
Ya usemos hibernate 3.6 o hibernate 4 y una u otra librería su uso es muy similar en ambas y se hace a través de anotaciones, aunque tambien se puede hacer a traves de los ficheros de mapeo de hibernate, las anotaciones son más recomendables y son de la siguiente forma:

...
import org.joda.time.DateTime;
...
@Type(type = "org.joda.time.contrib.hibernate.PersistentDateTime")
private DateTime fecha;
...

No hay más que usar la anotación @Type, es así de sencillo y una migración de los Date del JDK a DateTime de JodaTime no de debería ser muy complicada con la ayuda de un buen editor.

Si queremos establecer la fecha actual en el pasado o en el futuro podemos hacer uso del método de utilidad DateTimeUtils.setCurrentMillisFixed.

Referencia:
http://joda-time.sourceforge.net/contrib/hibernate/index.html
https://forums.oracle.com/forums/thread.jspa?threadID=1982257&start=0&tstart=0
http://joda-time.sourceforge.net/contrib/hibernate/userguide.html
http://usertype.sourceforge.net/