首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Hibernate java.util.Date 映射陷阱與解決方案

     編輯:Java 相關知識

映射對照表

Java 類型Hibernate 類型MySQL 類型
java.util.Date / java.sql.DatedateDATE
java.util.Date / java.sql.TimetimeTIME
java.util.Date / java.sql.TimestamptimestampTIMESTAMP

常見問題:timestamp 映射導致 equals 比較失敗

實體類別

public class User {
    private Date registerDate; // java.util.Date
    // getter/setter 略
}

映射檔

<property name="registerDate" type="timestamp" column="registerdate"/>

現象

User testUser = new User();
testUser.setRegisterDate(new Date());
session.save(testUser);
session.flush();
session.clear();

User savedUser = session.load(User.class, id);
// testUser.getRegisterDate().equals(savedUser.getRegisterDate()) → false
// 原因:testUser.registerDate 是 java.util.Date
// savedUser.registerDate 是 java.sql.Timestamp

根本原因

java.sql.Timestamp 繼承 java.util.Date,但覆寫 equals(Object):
Timestamp.equals(Object) 若參數非 Timestamp 實例,永遠回傳 false(因納秒精度未知)。
因此 Date.equals(Timestamp) 可能為 true,但 Timestamp.equals(Date) 必為 false —— 違反對稱性。

解決方案

方案一:Setter 正規化為 Date(推薦)

public void setRegisterDate(Date registerDate) {
    this.registerDate = new Date(registerDate.getTime()); // 截斷納秒
}

存入資料庫前統一轉為 java.util.Date,載入時 Hibernate 仍會產生 Timestamp,但比較時雙方皆為 Date 型別(若同時正規化),或改用 getTime() 比較毫秒數。

方案二:改用 Calendar 或 JSR-310 (Java 8+)

  • java.util.Calendar:Hibernate 支援 calendar / calendar_date 類型。
  • java.time.LocalDateTime / Instant:Hibernate 5.2+ 原生支援,精度明確、不可變、無 equals 陷阱。

方案三:自訂 UserType

public class DateAsTimestampUserType implements UserType {
    // 實作 nullSafeGet/Set,統一以 Timestamp 存取
}

映射時指定 type="com.yourpkg.DateAsTimestampUserType"。

最佳實踐建議

  1. 新專案優先使用 Java 8 java.time.* 類型。
  2. 舊專案若維持 java.util.Date,在 Setter 正規化毫秒數。
  3. 避免在業務邏輯直接用 equals() 比較日期,改比較 getTime() 或使用 compareTo()。
  4. 資料庫欄位型別選擇:
    DATE(僅日期)、TIME(僅時間)、TIMESTAMP(日期時間)、DATETIME(MySQL 專用,無時區轉換)。

結語

Hibernate 將 java.util.Date 映射為 timestamp 時,載入物件實為 java.sql.Timestamp,導致 equals 語義不對稱。理解此機制並採取正規化或升級至現代時間 API,可徹底規避此類 Bug。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved