Mapeo de fechas con @Temporal

Tutorial de JPA @Temporal

Mediante la anotación @Temporal es posible mapear las fechas con la base de datos de una forma simple. Una de las principales complicaciones cuando trabajamos con fecha y hora es determinar el formato empleado por el manejador de base de datos. Sin embargo, esto ya no será más problema con @Temporal.

Mediante el uso de @Temporal es posible determinar si nuestro atributo almacena Hora, Fecha u Hora y fecha, y es posible utilizar la clase Date o Calendar para estos fines. Yo siempre recomiendo utilizar Calendar, pues tiene muchas más operaciones para manipular fecha y hora.

Se pueden establecer tres posibles valores para la anotación:

  • DATE: Acotara el campo solo a la Fecha, descartando la hora.
    • @Temporal(TemporalType.DATE)
  • TIME: Acotara el campo solo a la Hora, descartando a la fecha.
    • @Temporal(TemporalType.TIME)
  • TIMESTAMP: Toma la fecha y hora.
    • @Temporal(TemporalType.TIMESTAMP)

Para ejemplificar como utilizar esta anotación retomaremos la Entidad Employee que ya hemos venido utilizando en todo este tutorial. En el pasado ya habíamos agregado un atributo llamado registDate que representaba la fecha de ingreso del empleado, pero no habíamos entrando en detalle, por lo que ahora será tiempo de regresar y analizarlo. Veamos como dejamos la entidad Employee:

package com.obb.jpa.jpaturorial.entity;

import java.util.Calendar;
import java.util.Objects;
import javax.persistence.*;

/**
 * @author Oscar Blancarte
 */
@Entity
@Table(
    name = "EMPLOYEES" , 
    schema = "jpatutorial", 
    indexes = {@Index(name = "name_index", columnList = "name",unique = true)}
)
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY, generator = "EmployeeTable")
    @Column(name = "ID")
    private Long id;
    
    @Column(name = "NAME", nullable = false, length = 150)
    private String name; 
    
    @Column(name = "SALARY", nullable = false, scale = 2)
    private double salary;
    
    @Column(name = "REGIST_DATE", updatable = false, nullable = false)
    @Temporal(TemporalType.DATE)
    private Calendar registDate;
    
    @Column(name="STATUS", nullable = false, length = 8 )
    @Enumerated(value = EnumType.STRING)
    private Status status;
    
    /**
     * GETs and SETs
     */
}

En este caso hemos determinado que la fecha de ingreso es solo fecha (DATE) puesto que no es de nuestro interés la hora. Observemos también que hemos definido la anotación @Column para definir el nombre de la columna contra la que mapea.

Tambíen los quiero invitar a ver mi curso de JPA, donde explico todos estos temas aplicados con API REST, https://codmind.com/courses/jpa

👉👉 Los invito a mi Curso de Mastering JPA, donde habla de todos estos temas y crearemos un API REST para probar todos los conceptos de persistencia.
👈👈

Veamos cómo quedaría la tabla generada hasta el momento:

@Temporal

Observa la columna REGIST_DATE es de tipo DATE.

NOTA: Este artículo es solo una sección del Tutorial de JPA, para ver el contenido completo de este tutorial regresa al Índice en el botón de abajo.

AnteriorÍndiceSiguiente

22 thoughts to “Mapeo de fechas con @Temporal”

    1. Hola Jose, esta es una pregunta muy típica y me suena que no tienes mucha experiencia en JavaEE en general. Para empezar, las Entidades las tienes un proyecto de tipo EJB y la aplicación JSF es una Web APP, por lo tanto, podríamos decir que son módulo diferentes. Desde JSE si que es posible obtener una referencia a la Entidad, pues solo basta con agregar el proyecto EJB como dependencia/librería, sin embargo, esto es una mala práctica, pues la entidades deberías de permanecer en la capa de negocio, es decir en el proyecto EJB. De esta forma, cuando requieres algún dado de la entidad o entidades, es se utilizan los DTO, los cuales son clases planes que tiene la información requerida en tu pantalla. Un DTO es la representación de una o más entidades, con la finalidad de realizar múltiples llamadas al Backend.

      Con respecto a como mostrarla en JSF, lo normal es crear SessiónBean, RequestBeans o ViewBeans a partir de la respuesta del Backend y luego utilizar el Bean en la vista, por ejemplo #{bean.fecha}, adicionalmente puedes aplicar una máscara con SimpleDateFormat para que se vea en el formato que requieras.

      Espero que esto resuelva tu duda.

      saludos.

      1. Gracias pero lo resovi utilizando algunas etiquetas de jsf.. ahora bien. para guardar una fecha con formato YYYY/MM/DD como lo haría porque estoy utilizando primefaces para agregar la fecha más facil por parte del usuario pero esta utiliza java.util.Date y mis clases estan mapeadas con java.util.Calendar

        Gracias de antemano

        1. Primero que nada, el formato de guardado lo defines en la base de datos, no en JPA, así que debes de buscar la documentación de la base de datos, con respecto a Date y Calendar, es realmente fácil, simplemente convierte el Date en un Calendar de la siguiente manera:

          Calendar cal = Calendar.getInstance();
          cal.setTime(date);

          Finalmente, cuando recuperas el Calendar por medio de JPA, puede obtener el Date através del Calendar.
          Date date = calendar.getTime();

          saludos.

          1. Si, esa es una forma fácil de sacarle la vuelta al problema, aunque yo te sugiero usar Calendar en las entidades, es mucho más potente el objeto Calendar que Date, pero si solo das mucho uso, entonces supongo que esta bien.

            saludos.

    1. Si omites la anotación quedaras a la suerte de la implementacion de JPA, que determinara automaticamente si el campo es solo fecha dd/mm/yyyy o fecha y hora dd/mm/yyyy hh:mm:ss, lo que puede producir un error en tiempo de ejecucion al momento de guardar, si el campo es date y JPA intenta guardar un Datetime

        1. Lo más seguro es que recupere el campo como DateTime, lo cual es perfectamente parseable a Date o Calendar, por lo que yo diría que no deberías de tener ningún problema, sin embargo, si esta fácil como agregar @Temporal, no vería por que no hacerlo, y así evitamos quedar a la merced de JPA.

          1. Gracias por la ayuda, lo que pasa es que por error omití colocarlo y en la consulta no me esta trayendo algunos registros, sin embargo como no es un error que no pueda replicar tan fácil, quería descartar la posibilidad de que el error surgiera de omitir la anotación.

            Muchas gracias.

          2. Si JPA te esta trayendo resultados, quiere decir que si logra parsear el campo, en otro caso, ni siquiera te trajera resultados, pues tronara todo el Query, por otra parte, si tu query utiliza esa fecha para realizar un Join o where, tienes que tener cuidado pues una fecha con hora difícilmente hace match con una sin hora

  1. Una Consulta en relación a las fechas.
    Soy nuevo con Java y Spring. Desarrollé un crud con una tabla, agregué Spring security, etc.
    Tengo un problema con la fecha. Al ingresar el dato está correcto(probé con input type string y date). Al ver la fecha en la base de datos MySQL está correcta. El tema surge cuando muestro la fecha, me muestra la fecha del día anterior. Me dijeron que es un problema de java no de thymeleaf. Agregue un código que tampoco resultó….

    Acá está el video……

    https://youtu.be/K_Bdob74Y-g

    1. Hola Alex, jamás me había pasado algo similar, seguramente el problema está en la forma en que se parsea la fecha de la base de datos a un objeto Date, veo que usas la anotación @DateTimeFormat, intenta quitarla para ver si el problema se arregla.
      saludos

  2. buenas, tengo un problema si me puedes ayudar: en una tabla en MYSQL tengo 2 atributos (fecha, hora), un Date y un Time, sin embargo en la aplicacion (en el JpaController) el atributo “TIME” me lo guarda como “Date”, y no puedo acceder al tiempo cuando quiero listar los datos en una tabla, mi pregunta es le tengo que cambiar Calendar a la hora en java, hay otra forma? porque intente asignarle Time (sql.time) pero aparentemente solo se puede usar util.Date y util.Calendar

    1. Hola Ivan, yo te recomiendo que siempre uses Calendar además, agrega la anotación @Temporal, esta anotación recibe el formato de la fecha (TemporalType).

      saludos.

    1. Hola Rene, JPA funciona igual en EJB o en Spring Boot, tendrás que hacer un Query filtrando por fecha “select e from Entity e where date = :date” y pasas el parámetro mediante Query.setParameter(“date”, fecha)

    1. Es totalmente independiente, en el front puedes usar un String de cualquier tipo o un objeto Date, lo importante es que cuando llegue al Backend, este sepa como interpretar el dato.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *