2013-01-07 129 views
3

我找到了一種方法來創建我想用UTC時區哪個日期: Java Date and Daylight SavingJava的夏令時和Hibernate

這樣我就可以打造「陽光03月25日02:00:00」,但是當我插入此日期Hibernate,它不寫它,似乎休眠使用不能覆蓋的不同時區。

我的問題是,我不能在我的Hibernate/H2數據庫中插入這個日期:「Sun 3月25日02:00:00」如果我使用UTC時區,也不會。

更新1: 我試圖插入這些值:

Sun Mar 25 01:00:00 UTC 2012 
Sun Mar 25 02:00:00 UTC 2012 
Sun Mar 25 03:00:00 UTC 2012 
Sun Mar 25 04:00:00 UTC 2012 
Sun Mar 25 05:00:00 UTC 2012 
Sun Mar 25 06:00:00 UTC 2012 
Sun Mar 25 07:00:00 UTC 2012 
Sun Mar 25 08:00:00 UTC 2012 
Sun Mar 25 09:00:00 UTC 2012 
Sun Mar 25 10:00:00 UTC 2012 
Sun Mar 25 11:00:00 UTC 2012 
Sun Mar 25 12:00:00 UTC 2012 
Sun Mar 25 13:00:00 UTC 2012 
Sun Mar 25 14:00:00 UTC 2012 
Sun Mar 25 15:00:00 UTC 2012 
Sun Mar 25 16:00:00 UTC 2012 
Sun Mar 25 17:00:00 UTC 2012 
Sun Mar 25 18:00:00 UTC 2012 
Sun Mar 25 19:00:00 UTC 2012 
Sun Mar 25 20:00:00 UTC 2012 
Sun Mar 25 21:00:00 UTC 2012 
Sun Mar 25 22:00:00 UTC 2012 
Sun Mar 25 23:00:00 UTC 2012 

,但在數據庫中有這些:

in the database

+0

從這個問題和你的另一個*你想要哪個* 2am還不清楚。凌晨2點UTC?或在當地時區凌晨2點?你說你*不能*插入價值 - 當你嘗試時會發生什麼?更新了 –

+0

。這不是重要的時區,我會插入「2012年3月25日02:00:00」,但它不起作用。 – tyranitar

+3

時區*絕對*重要。你的數據庫本身是否有任何時區設置? –

回答

1

這是JDBC的 「功能」,而不是Hibernate。因此,您可以在jdbc選項(hibernate.cfg.xml中的jdbc連接字符串)中更改此行爲,而不是在Hibernate選項中。默認情況下,日期值總是保存在客戶端應用程序的時區中(而不是數據庫的時區,因爲它似乎是更多的邏輯)。 MySQL例如知道jdbc連接選項,它強制數據庫始終以UTC存儲日期值。我不知道H2是否知道這樣的選擇,可能不是。

在你的例子中,3月25日是白天第一天,你的。 3月25日02:00在你的時區不存在,這就是爲什麼你沒有在數據庫中找到它。

如果你不想在連接字符串中的一個選項(其中有缺點,可能並不適用於所有數據庫),有三種可能如何去解決該問題:

  1. 插入前讀完之後你會在你的程序中進行時區對話。除此之外,對於您的普通getter get/setMyTime(),您只爲Hibernate get/setHibernateMyTime()編寫額外的getter和setter,您可以在其中執行時區轉換以及您在映射文件或註釋中使用的地方。對於時區轉換,您可以使用TimeZone.getOffset()。

  2. 使用字符串而不是日期。在這種情況下,您不需要進行時區轉換,但必須將字符串轉換爲日期,反之亦然。

  3. 使用UTC作爲本地時間運行應用程序。如果在任何地方需要用戶的本地時間,例如在用戶界面中,則這具有缺點。

我們在我們的應用程序中做了解決方案1。

+0

我選擇了2號解決方案 – tyranitar

0

正如約翰娜所說,有幾個選擇如何處理這個時區轉移問題。還有一篇文章更詳細地解釋了這個問題,提供了更多的例子和解決方案。

就上一個答案中的選項編號1而言,如果您不想自己編寫所有代碼,則可以使用小型開源庫DbAssist 。它將java.util.Datejava.util.Timestamp映射到自定義UtcDateType,該自定義內部覆蓋了setter和getter,因此無論何時讀取或寫入數據庫,它都會將數據庫中的日期視爲UTC時區。這是一個方便的解決方案,因爲你根本沒有改變你的實體類。

所有你所要做的就是增加的依賴(與你的Hibernate的版本替換5.2.2):

<dependency> 
    <groupId>com.montrosesoftware</groupId> 
    <artifactId>DbAssist-5.2.2</artifactId> 
    <version>1.0-RELEASE</version> 
</dependency> 

然後應用修復作爲該項目的github安裝手冊的說明。我不在這裏複製它,因爲它取決於您是使用JPA Annotations還是HBM文件映射您的實體字段而有所不同;這是一個簡單的單線設置。

0

你能解釋你的表的數據結構嗎?您是否在使用DATETIME或TIMESTAMP作爲該列?

根據MySQL官方文檔 - MySQL將TIMESTAMP值從當前時區轉換爲UTC存儲,並從UTC返回到當前時區以供檢索。它使用JDBC連接的當前時區進行此轉換。

這種行爲很奇怪,但是正確的,「Sun 3月25日02:00:00」不存在於您的時區(可能是中歐)。如果您需要保存該日期,則可以將該列創建爲DATETIME。