2012-01-23 75 views
62

他們幸福地結婚了嗎?hibernate 4和joda-time

我正在使用最新版本的hibernate(4)和版本1.3的joda-time hibernate support,我也認爲這是最新版本。

一切似乎都使用註釋時必須工作正常(如預期中創建日期列):

@Column 
@Type(type="org.joda.time.contrib.hibernate.PersistentLocalDate") 
private LocalDate myDate; 

是他們與使用這些版本在一起的任何已知問題?

更新 那麼原來獲得創建列,但無法與任何數據來填充:

處理程序處理失敗;嵌套的例外是java.lang.AbstractMethodError:org.joda.time.contrib.hibernate.PersistentLocalDateTime.nullSafeSet

他們是不相容的,我應該使用usertype請參閱下面的答案。

+0

你剛剛告訴我們他們*一起工作,不是嗎? – skaffman

+0

@skaffman我沒有測試除列創建之外的任何其他東西......這是我的理解,以前的版本(joda-time lib)必須重新編譯爲新版本的hibernate。這響起了一個警報 - 因此,這個問題... – NimChimpsky

+0

他們並不幸福結婚,休眠是有其他關係...和喬達..:/ ..她受傷 – nobalG

回答

96

明顯缺乏文檔,意味着我可能會寫下集成所需的步驟。確保你的庫是最新的。

你需要:假設你已經有了hibernate4]

最新的喬達時版本

<dependency> 
    <groupId>joda-time</groupId> 
    <artifactId>joda-time</artifactId> 
    <version>2.0</version> 
</dependency> 

和用戶類型的lib

<dependency> 
    <groupId>org.jadira.usertype</groupId> 
    <artifactId>usertype.core</artifactId> 
    <version>3.0.0.CR1</version> 
</dependency> 

然後用在實體類以下(不一定是LocalDateTime,可以是任何可用的持久類):

import org.joda.time.LocalDateTime; 

和列定義:

@Column(name="updated", nullable = false) 
@Type(type="org.jadira.usertype.dateandtime.joda.PersistentLocalDateTime") 
private LocalDateTime updated; 
+1

我們如何知道它在我們的選擇數據庫中映射到的類型? – benstpierre

+0

@Benju看看數據庫表創建後... – NimChimpsky

+0

對,所以使用自動生成表並查看輸出? – benstpierre

29

我會,因爲這是在我看來,重要的信息添加爲一個單獨的答案的人升級到Hibernate 4,並在需要遷移到使用jadira的持續時間類型。這個頁面在hibernate 4和jodatime的谷歌搜索結果中排名很高,所以我會在這裏添加它。 (有關此問題的單獨討論,請參閱:Joda time DateTime incorrectly stores in database

如果您位於UTC以外的時區,則需要重要的配置以獲得與使用喬達時間休眠時相同的行爲 - 支持類型。 jadira的時態類型默認工作的方式是在持久化數據庫之前將所有值轉換爲UTC時區,並在從數據庫加載值時轉換回系統的時區。

升級後我被燒燬了,當時我有很多時間戳與數據庫中的確切時區(UTC + 1(夏令時+2))。在升級到Hibernate之後加載4,1或2小時(取決於時間戳是否在夏令時)被添加到數據庫中的值,這意味着所有現有的時間戳都被錯誤地顯示。此外,新時間戳值與UTC時區一起存儲在數據庫中,導致它們在應用程序中正確顯示,但在數據庫中出錯。總而言之,時區和時間戳的混亂。

因此,爲了獲得與joda-time相同的行爲hibernate-support(日期時間被持久化爲相關服務器的時區,並且數據庫中的時間戳與正在加載的時間戳相同到應用程序),以下屬性必須被添加到JPA/Hibernate配置(在我的情況,hibernate.properties):

jadira.usertype.autoRegisterUserTypes=true 
jadira.usertype.databaseZone=jvm 
jadira.usertype.javaZone=jvm 

這將確保在數據庫中的時間戳將是相同的時區作爲中的應用程序,這反過來將是jvm的時區(大多數情況下是應用程序服務器的時鐘)。

而且,從我的理解中,autoRegisterUserTypes -property不再需要爲@Type -annotation爲選擇常見的類型,它們之間的Jodatime類型DateTimeLocalDate的。

+2

既然你已經解決了你的問題,並且它與這個問題沒有直接關係,我會刪除我的評論並標記你的刪除,所以我們保留評論部分的清晰和重點。 – Tobb

+0

拋開一個問題:爲什麼不用UTC時間存儲每個時間戳?如果服務器移動到不同的時區呢? Imho最好以UTC時間存儲所有時間戳,並讓客戶決定他在哪個時區。 – displayname

+0

作爲一般規則,我會同意。就我而言,服務器沒有機會移動到不同的時區。此外,這裏的問題是默認行爲改變,在我的情況下,我的知識。因此,當您不知道發生這種情況時,您無法遷移您的數據,最終得到一組具有不同時區的時間戳,這當然不好。但是,如果您的項目有意義,則可以跳過此處提供的設置,而是遷移數據庫。有一點對於全天候UTC來說是消極的,那就是SQL報告不是很棘手就是錯誤。 – Tobb