Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

JPA Salvando data errada no banco de dados MySQL

tl;dr


Usar JPA 2.2 por seu suporte a java.time .

Use uma classe somente de data em Java para trabalhar com valores somente de data em 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.time


JPA 2.2 agora suporta o moderno java.time Aulas. Não há mais necessidade de usar Joda-Time.

Não use java.sql.Date . Essa classe faz de conta para representar apenas uma data, mas na verdade tem uma hora do dia definida como UTC devido à terrível decisão de design de herdar de java.util.Date (que apesar do nome representa uma data e uma hora do dia e um deslocamento de zero para o próprio UTC). Essas classes legadas são uma bagunça terrível e miserável. A Sun, Oracle e a comunidade JCP desistiram dessas aulas anos atrás com a adoção do JSR 310, e você também deveria.

LocalDate


O LocalDate class representa um valor somente de data sem hora do dia e sem fuso horário ou offset-from-UTC .

Um fuso horário é crucial para determinar uma data. Para qualquer momento, a data varia em todo o mundo por zona. Por exemplo, alguns minutos depois da meia-noite em Paris França é um novo dia enquanto ainda “ontem” em Montréal Québec .

Se nenhum fuso horário for especificado, a JVM aplicará implicitamente seu fuso horário padrão atual. Esse padrão pode alterar a qualquer momento durante o tempo de execução(!), então seus resultados podem variar. Melhor especificar seu fuso horário desejado/esperado explicitamente como um argumento. Se crítico, confirme a zona com seu usuário.

Especifique um nome de fuso horário adequado no formato de Continente/Região , como América/Montreal , África/Casablanca , ou Pacífico/Auckland . Nunca use a abreviação de 2-4 letras, como EST ou IST como eles não fusos horários verdadeiros, não padronizados e nem mesmo únicos(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

Se você quiser usar o fuso horário padrão atual da JVM, peça e passe como argumento. Se omitido, o código torna-se ambíguo de ler, pois não sabemos ao certo se você pretendia usar o padrão ou se, como muitos programadores, não sabia do problema.
ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

Ou especifique uma data. Você pode definir o mês por um número, com a numeração sã de 1 a 12 para janeiro-dezembro.
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.

Ou, melhor, use o Mês objetos enum pré-definidos, um para cada mês do ano. Dica:use estes Mês objetos em toda a sua base de código em vez de um mero número inteiro para tornar seu código mais autodocumentado, garantir valores válidos e fornecer segurança de tipo . Idem para Ano &YearMonth .
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;

Matemática de data e hora


Aparentemente, você deseja começar com uma data e obter um mês depois como um intervalo de datas.
LocalDate monthLater = ld.plusMonths( 1 ) ;

JDBC 4.2


A partir do JDBC 4.2, seu driver JDBC é necessário para suportar algumas das chaves java.time classes como LocalDate .

Período


Observe os links abaixo para ThreeTen-Extra . Você pode encontrar o LocalDateRange class lá para ser útil se você trabalhar muito com intervalos de datas.

Sobre java.time


O java.time framework é construído em Java 8 e posterior. Essas classes substituem o antigo e problemático legado classes de data e hora, como java. util.Data , Calendário , &SimpleDateFormat .

Para saber mais, consulte o Tutorial do Oracle . E pesquise no Stack Overflow muitos exemplos e explicações. A especificação é JSR 310 .

O Joda-Time projeto, agora em modo de manutenção , aconselha a migração para o java.time Aulas.

Você pode trocar java.time objetos diretamente com seu banco de dados. Use um driver JDBC compatível com JDBC 4.2 ou mais tarde. Não há necessidade de strings, não há necessidade de java.sql.* Aulas.

Onde obter as classes java.time?

O ThreeTen-Extra projeto estende java.time com classes adicionais. Este projeto é um campo de provas para possíveis adições futuras ao java.time. Você pode encontrar algumas classes úteis aqui, como Intervalo , YearWeek , YearQuarter e mais .