sql >> Base de Datos >  >> RDS >> Mysql

JPA Guardando una fecha incorrecta en la base de datos MySQL

tl;dr

Utilice JPA 2.2 por su apoyo a java.time .

Use una clase de solo fecha en Java para trabajar con valores de solo fecha en SQL.

LocalDate                           // Represent a date-only, without a time-of-day and without a time zone.
.now(                               // Get today's date…
    ZoneId.of( "Africa/Tunis" )     // …as seen in the wall-clock time used by the people of a particular region.
)                                   // Returns a `LocalDate` object.
.plusMonths( 1 )                    // Returns another `LocalDate` object, per immutable objects pattern.

java.tiempo

JPA 2.2 ahora es compatible con el moderno java.time clases Ya no es necesario usar Joda-Time.

Hacer no use java.sql.Date . Esa clase simula para representar solo una fecha, pero en realidad tiene una hora del día establecida en UTC debido a la terrible decisión de diseño de heredar de java.util.Date (que a pesar del nombre representa una fecha y una hora del día y un desplazamiento de cero para el propio UTC). Estas clases heredadas son un desastre horrible y miserable. Sun, Oracle y la comunidad de JCP renunciaron a estas clases hace años con la adopción de JSR 310, y usted también debería hacerlo.

LocalDate

El LocalDate class representa un valor de solo fecha sin hora del día y sin zona horaria o offset-from-UTC .

Una zona horaria es crucial para determinar una fecha. Para cualquier momento dado, la fecha varía en todo el mundo por zona. Por ejemplo, unos minutos después de la medianoche en París Francia es un nuevo día cuando aún es “ayer” en Montréal Québec .

Si no se especifica ninguna zona horaria, la JVM aplica implícitamente su zona horaria predeterminada actual. Ese valor predeterminado puede cambiar en cualquier momento durante el tiempo de ejecución (!), por lo que sus resultados pueden variar. Es mejor especificar la zona horaria deseada/esperada explícitamente como argumento. Si es crítico, confirme la zona con su usuario.

Especifique un nombre de zona horaria adecuado en el formato de Continent/Region , como America/Montreal , Africa/Casablanca o Pacific/Auckland . Nunca use la abreviatura de 2-4 letras como EST o IST como son no zonas horarias verdaderas, no estandarizadas y ni siquiera únicas (!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

Si desea utilizar la zona horaria predeterminada actual de la JVM, solicítela y pásela como argumento. Si se omite, el código se vuelve ambiguo para leer, ya que no sabemos con certeza si tenía la intención de usar el valor predeterminado o si, como tantos programadores, no estaba al tanto del problema.

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

O especificar una fecha. Puede configurar el mes con un número, con la misma numeración del 1 al 12 para enero-diciembre.

LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ;  // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.

O, mejor, use el Month enum objetos predefinidos, uno para cada mes del año. Sugerencia:Utilice estos Month objetos a lo largo de su base de código en lugar de un mero número entero para que su código sea más autodocumentado, garantice valores válidos y proporcione tipo-seguridad . Lo mismo ocurre con Year &YearMonth .

LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;

Matemáticas de fecha y hora

Aparentemente, desea comenzar con una fecha y obtener un mes más tarde como rango de fechas.

LocalDate monthLater = ld.plusMonths( 1 ) ;

JDBC 4.2

A partir de JDBC 4.2, se requiere que su controlador JDBC admita algunas de las claves java.time clases como LocalDate .

Intervalo de fechas

Tenga en cuenta los enlaces a continuación para ThreeTen-Extra . Puede encontrar el LocalDateRange class allí para ser útil si trabaja mucho con rangos de fechas.

Acerca de java.time

El java.time framework está integrado en Java 8 y versiones posteriores. Estas clases reemplazan al viejo y problemático legacy clases de fecha y hora como java.util.Date , Calendar , &SimpleDateFormat .

Para obtener más información, consulte el Tutorial de Oracle . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .

El Joda-Time proyecto, ahora en modo de mantenimiento , recomienda la migración a java.time clases.

Puede intercambiar java.time objetos directamente con su base de datos. Use un controlador JDBC compatible con JDBC 4.2 o después. Sin necesidad de cadenas, sin necesidad de java.sql.* clases.

¿Dónde obtener las clases java.time?

El ThreeTen-Extra proyecto extiende java.time con clases adicionales. Este proyecto es un campo de pruebas para posibles adiciones futuras a java.time. Puede encontrar algunas clases útiles aquí, como Interval , YearWeek , YearQuarter y más .