Mysql
 sql >> Datenbank >  >> RDS >> Mysql

JPA Speichert falsches Datum in MySQL-Datenbank

tl;dr

Verwenden Sie JPA 2.2 für die Unterstützung von java.time .

Verwenden Sie eine Nur-Datum-Klasse in Java, um mit Nur-Datum-Werten in SQL zu arbeiten.

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 unterstützt jetzt die moderne java.time Klassen. Joda-Time muss nicht mehr verwendet werden.

Tut nicht Verwenden Sie java.sql.Date . Diese Klasse täuscht vor um nur ein Datum darzustellen, hat aber aufgrund der schrecklichen Designentscheidung, von java.util.Date zu erben, tatsächlich eine Uhrzeit auf UTC gesetzt (was trotz des Namens ein Datum darstellt und eine Tageszeit und ein Offset von Null für UTC selbst). Diese Legacy-Klassen sind ein schreckliches Durcheinander. Sun, Oracle und die JCP-Community haben diese Klassen vor Jahren mit der Einführung von JSR 310 aufgegeben, und Sie sollten das auch tun.

LocalDate

Das LocalDate Klasse repräsentiert einen reinen Datumswert ohne Tageszeit und ohne Zeitzone oder offset-from-UTC .

Eine Zeitzone ist entscheidend für die Bestimmung eines Datums. Für jeden bestimmten Moment variiert das Datum rund um den Globus je nach Zone. Zum Beispiel wenige Minuten nach Mitternacht in Paris Frankreich ist ein neuer Tag, während es in Montréal Québec noch "gestern" ist .

Wenn keine Zeitzone angegeben ist, wendet die JVM implizit ihre aktuelle Standardzeitzone an. Dieser Standard kann jederzeit ändern während der Laufzeit (!), sodass Ihre Ergebnisse variieren können. Geben Sie Ihre gewünschte/erwartete Zeitzone besser explizit als Argument an. Falls kritisch, bestätigen Sie die Zone mit Ihrem Benutzer.

Geben Sie einen richtigen Zeitzonennamen an im Format Continent/Region , wie z. B. America/Montreal , Africa/Casablanca , oder Pacific/Auckland . Verwenden Sie niemals die aus 2-4 Buchstaben bestehende Abkürzung wie EST oder IST da sie es nicht sind echte Zeitzonen, nicht standardisiert und nicht einmal eindeutig (!).

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

Wenn Sie die aktuelle Standardzeitzone der JVM verwenden möchten, fragen Sie danach und übergeben Sie sie als Argument. Wenn es weggelassen wird, wird der Code uneindeutig, da wir nicht sicher wissen, ob Sie beabsichtigten, die Standardeinstellung zu verwenden, oder ob Sie, wie so viele Programmierer, sich des Problems nicht bewusst waren.

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

Oder geben Sie ein Datum an. Sie können den Monat durch eine Zahl einstellen, mit vernünftiger Nummerierung 1-12 für Januar-Dezember.

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.

Oder verwenden Sie besser den Month Enum-Objekte vordefiniert, eines für jeden Monat des Jahres. Tipp:Verwenden Sie diesen Month Objekte in Ihrer gesamten Codebasis und nicht nur eine ganze Zahl, um Ihren Code selbstdokumentierender zu machen, gültige Werte sicherzustellen und Typsicherheit . Dasselbe gilt für Year &YearMonth .

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

Datum-Zeit-Mathematik

Anscheinend möchten Sie mit einem Datum beginnen und einen Monat später als Datumsbereich erhalten.

LocalDate monthLater = ld.plusMonths( 1 ) ;

JDBC 4.2

Ab JDBC 4.2 muss Ihr JDBC-Treiber einige der Schlüssel java.time unterstützen Klassen wie LocalDate .

Zeitraum

Beachten Sie die Links unten für ThreeTen-Extra . Möglicherweise finden Sie den LocalDateRange Klasse praktisch, wenn Sie viel mit Datumsbereichen arbeiten.

Über java.time

Der java.time Framework ist in Java 8 und höher integriert. Diese Klassen ersetzen das lästige alte Legacy Datumszeitklassen wie java.util.Date , Calendar , &SimpleDateFormat .

Weitere Informationen finden Sie im Oracle-Tutorial . Und durchsuchen Sie Stack Overflow nach vielen Beispielen und Erklärungen. Die Spezifikation ist JSR 310 .

Die Joda-Time Projekt, jetzt im Wartungsmodus , empfiehlt die Migration zu java.time Klassen.

Sie können java.time austauschen Objekte direkt mit Ihrer Datenbank. Verwenden Sie einen JDBC-Treiber kompatibel mit JDBC 4.2 oder später. Keine Notwendigkeit für Strings, keine Notwendigkeit für java.sql.* Klassen.

Wo erhalte ich die java.time-Klassen?

Das ThreeTen-Extra project erweitert java.time um zusätzliche Klassen. Dieses Projekt ist ein Testgelände für mögliche zukünftige Ergänzungen zu java.time. Hier finden Sie einige nützliche Klassen wie Interval , YearWeek , YearQuarter , und mehr .