2017-02-19 68 views
13

我有這兩個類複製TIMESTAMP到DATETIME關於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; 
} 

當使用休眠,我分配

destination.myInstant = source.myInstant; 

,然後將存儲的值比原來的1小時較小 - 根據命令行MySQL客戶端和Java。我目前的時區是UTC + 1,所以原因顯然是時區轉換。

有幾個地方這可以修復,但我正在尋找最佳實踐。服務器應該在全球範圍內工作,所以它應該繼續在內部使用UTC,對吧?

我應該只是將列類型更改爲TIMESTAMP?那麼,爲什麼Instant默認映射到DATETIME


this articleInstant確實地圖TIMESTAMP,但在我的情況下,它沒有。爲什麼?

+0

請提供'SHOW CREATE TABLE'和Hibernate生成的SQL。 –

+0

@RickJames這裏沒有什麼有趣的東西:'SHOW CREATE TABLE'顯示類似'timestamp(3)NOT NULL DEFAULT'2016-01-01 01:00:00:00和'datetime'。這些陳述僅僅是簡單的選擇和更新,沒有邏輯背後。這些值沒有被記錄。無論如何,我會發布日誌,但我不得不用我的問題中使用的替換真正的類和字段名稱,這是不值得的,因爲那裏沒有任何東西。 – maaartinus

+0

'SHOW VARIABLES LIKE'%zone%';' –

回答

1

在上面的MySQL 5 &中,TIMESTAMP值從當前時區轉換爲UTC存儲,並從UTC轉換回當前時區以供檢索。這隻發生在TIMESTAMP數據類型上,但不適用於DATETIME。這就是您在將TIMESTAMP分配給DATETIME時看到差異的原因。所以,有兩個相同類型的列應該工作。 Hibernate默認將InstantType映射到數據庫TIMESTAMP類型。儘管您可以在MYSQL中將它用於TIMESTAMP和DATETIME,但它們的處理方式不同。

5

如果你想使用時區和Java 8,我會推薦使用ZonedDateTime或OffsetTimeZone(在使用Hibernate時後者是首選)。對於舊版本使用日曆。

  • 當你實例它應該默認情況下與你的計算機的時區。
  • 檢查數據庫是否帶時區或不帶時區。
  • 您設置的默認值也沒有時區,如果它是「帶時區」,它應該自動添加數據庫的偏移量。

我希望這一些工作。以下是我在其中一個項目中所做的工作。

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

我對你的回答並不滿意,但這不是你的錯。我將不得不調查更多的實際情況(請參閱我對瑞克詹姆斯的回答)。 – maaartinus