2017-02-19 50 views
13

mam tych dwóch klasKopiowanie TIMESTAMP do DATETIME na MySQL Hibernate

class Source { 
    // mapped to TIMESTAMP 
    @Version 
    @Column(columnDefinition="TIMESTAMP(3) DEFAULT '2016-01-01'") 
    Instant myInstant; 
} 

class Destination { 
    // mapped to DATETIME 
    @Basic(optional=true) 
    Instant myInstant; 
} 

Przy użyciu Hibernate, przypisać

destination.myInstant = source.myInstant; 

a następnie zapisana wartość jest mniejsza o jedną godzinę niż oryginał - zarówno zgodnie z klientem MySQL z linii poleceń, jak i Java. Moja aktualna strefa czasowa to UTC + 1, więc powodem jest oczywiście konwersja strefy czasowej.

Jest kilka miejsc, w których można to naprawić, ale szukam najlepszej praktyki. Serwer powinien działać na całym świecie, więc powinien nadal używać UTC wewnętrznie, prawda?

Czy powinienem zmienić typ kolumny na TIMESTAMP? Dlaczego domyślnie Instant jest mapowane na DATETIME?


Według this article, Instantrobi mapę do TIMESTAMP, ale w moim przypadku tak się nie stało. Czemu?

+0

Proszę podać 'SHOW CREATE TABLE' i SQL wygenerowany z Hibernate. –

+0

@RickJames Nie ma tam nic ciekawego: 'SHOW CREATE TABLE' pokazuje typy takie jak' timestamp (3) NOT NULL DEFAULT '2016-01-01 01: 00: 00.000' i 'datetime'. Wyrażenia są prostym wyborem i aktualizacją bez logiki. Wartości nie zostały zarejestrowane. Mimo to bym opublikował log, ale musiałbym zastąpić prawdziwe nazwy klas i pól przez te, których użyto w moim pytaniu, a to nie jest tego warte, ponieważ tam naprawdę nic nie ma. – maaartinus

+0

'POKAŻ ZMIENNY JAK"% zone% ";' –

Odpowiedz

1

Powyżej, w MySQL 5 & powyżej, wartości TIMESTAMP są konwertowane z bieżącej strefy czasowej na UTC do przechowywania i są przekształcane z UTC na bieżącą strefę czasową do pobierania. Występuje tylko dla typu danych TIMESTAMP, ale nie dla DATETIME. To jest powód, dla którego widzisz różnicę podczas przypisywania TIMESTAMP do DATETIME. Zatem, powinny działać obie kolumny tego samego typu. Hibernuj domyślnie mapy InstantType do bazy danych typu TIMESTAMP. Chociaż można go używać zarówno dla TIMESTAMP, jak i DATETIME w MYSQL, są one obsługiwane inaczej.

5

Jeśli chcesz pracować z strefami czasowymi i językiem Java 8, polecam używanie ZonedDateTime lub OffsetTimeZone (ten ostatni jest preferowany podczas pracy z Hibernate). W przypadku starszych wersji użyj Kalendarza.

  • Po zainstalowaniu instancji domyślnie powinna być strefa czasowa komputera.
  • Sprawdź, czy baza danych to sygnatura czasowa z strefą czasową lub bez niej.
  • Ustawiona domyślnie jest również bez strefy czasowej, a jeśli jest "ze strefą czasową", powinna automatycznie dodać przesunięcie bazy danych.

Mam nadzieję, że niektóre z tych prac. Oto jak to zrobiłem w jednym z moich projektów.

@Column(name = "registration_time") 
private OffsetDateTime registrationTime; 
[...] 
subscriber.setRegistrationTime(OffsetDateTime.now()); 
+0

Nie jestem całkowicie zadowolony z twojej odpowiedzi, ale to nie twoja wina. Będę musiał zbadać więcej tego, co się dzieje (zobacz moją odpowiedź do Ricka Jamesa). – maaartinus