MySQL 表中有 YEAR(4) 類型字段 (如 birth_year),Java 實體類對應屬性為 java.sql.Date,需將字符串 "1990" 正確保存。
YEAR 存儲 1901-2155 年份,1 字節。Integer / int (最推薦,直接對應年份數值)Short / shortjava.sql.Date (需設置具體日期, 如 1990-01-01, 但僅年份有效)java.time.Year (Java 8+, 需自定義類型映射)
// 實體類
@Entity
@Table(name = "user")
public class User {
@Id @GeneratedValue
private Long id;
@Column(name = "birth_year", columnDefinition = "YEAR")
private Integer birthYear; // 對應 YEAR 類型
// getter/setter
public Integer getBirthYear() { return birthYear; }
public void setBirthYear(Integer birthYear) { this.birthYear = birthYear; }
}
// Service 中賦值保存
String s = "1990";
User user = new User();
user.setBirthYear(Integer.parseInt(s)); // 字符串轉 Integer
session.save(user); // 或 hibernateTemplate.save(user)
// 實體類
@Column(name = "birth_year")
@Type(type = "java.sql.Date") // 或依賴默認映射
private Date birthYear; // java.sql.Date
// 賦值邏輯
String s = "1990";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
try {
java.util.Date utilDate = sdf.parse(s); // 解析為 1990-01-01 00:00:00
user.setBirthYear(new java.sql.Date(utilDate.getTime())); // 轉 sql.Date
} catch (ParseException e) { /* 處理異常 */ }
session.save(user);
注意:數據庫存儲時僅保留年份部分,讀出時日期會變為該年的 1 月 1 日。
// 實現 UserType
public class YearUserType implements UserType {
@Override public int[] sqlTypes() { return new int[]{Types.SMALLINT}; } // YEAR 映射為 SMALLINT
@Override public Class returnedClass() { return Year.class; }
@Override public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws SQLException {
int year = rs.getInt(names[0]);
return year != 0 ? Year.of(year) : null;
}
@Override public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws SQLException {
if (value == null) st.setNull(index, Types.SMALLINT);
else st.setInt(index, ((Year)value).getValue());
}
// ... 其他方法按規範實現 ...
}
// 實體類使用
@Type(type = "com.example.type.YearUserType")
@Column(name = "birth_year")
private Year birthYear;
// 賦值
user.setBirthYear(Year.parse("1990")); // Year.of(1990)
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| Integer | 簡單、高效、無轉換損失、類型安全 | 無 | 絕大多數業務場景 首選 |
| java.sql.Date | 兼容舊代碼/日期 API | 需解析格式化、存讀不對稱 (日期變 1月1日) | 歷史項目維護 |
| java.time.Year + UserType | 語義豐富、類型安全、現代 API | 需編寫樣板代碼、增加複雜度 | 領域模型驅動設計、嚴格類型要求 |
核心提示:確保實體屬性類型與數據庫列類型在 Hibernate 映射中兼容,Integer 是處理 MySQL YEAR 最自然的選擇。