1. 概述
在日常开发中,我们经常需要在 java.time.LocalDate
和 java.sql.Date
之间做转换。尤其是在使用 JPA 或其他 ORM 框架时,这种需求尤为常见。
本文将带你快速掌握几种常用的转换方式,让你在处理日期类型时更加得心应手 ✅
2. 直接转换
最简单的转换方式就是使用 java.sql.Date
提供的静态方法。
2.1 LocalDate 转 java.sql.Date
使用 Date.valueOf()
方法即可完成转换:
Date date = Date.valueOf(LocalDate.now());
或者指定一个具体日期:
Date date = Date.valueOf(LocalDate.of(2019, 1, 10));
⚠️ 注意:如果传入的是 null
,会抛出 NullPointerException
。
2.2 java.sql.Date 转 LocalDate
反过来,使用 toLocalDate()
方法即可:
LocalDate localDate = Date.valueOf("2019-01-10").toLocalDate();
简单粗暴,没有多余操作 ✅
3. 使用 AttributeConverter
3.1 问题背景
虽然 Java 8 引入了强大的 Date/Time API,但在与数据库交互时,尤其是在使用 JPA 时,LocalDate
可能会被映射成 blob
类型,而不是我们期望的 DATE
类型。
为了避免每次都手动转换,我们可以使用 JPA 提供的 AttributeConverter
接口来自动处理转换逻辑。
3.2 实现转换器
下面是一个简单的 AttributeConverter
实现:
@Converter(autoApply = true)
public class LocalDateConverter implements AttributeConverter<LocalDate, Date> {
@Override
public Date convertToDatabaseColumn(LocalDate localDate) {
return Optional.ofNullable(localDate)
.map(Date::valueOf)
.orElse(null);
}
@Override
public LocalDate convertToEntityAttribute(Date date) {
return Optional.ofNullable(date)
.map(Date::toLocalDate)
.orElse(null);
}
}
这个转换器做了两件事:
- 将
LocalDate
自动转换为java.sql.Date
存入数据库 - 从数据库读取时,自动将
java.sql.Date
转回LocalDate
📌 加上 @Converter(autoApply = true)
后,这个转换器会自动应用到所有 LocalDate
字段上,无需额外配置。
4. LocalDateTime 转 java.sql.Date
有时候我们拿到的是 LocalDateTime
,但只想存日期部分(年月日),这时也需要转成 java.sql.Date
。
⚠️ 注意:java.sql.Date
是不带时间的,只保留日期部分。
4.1 转换方式
由于 LocalDateTime
包含时间信息,我们需要先转成 LocalDate
,再转成 java.sql.Date
:
@Test
void givenALocalDateTime_whenConvertingToSqlDate_thenReturnSqlDateWithoutTime() {
LocalDateTime givenLocalDateTime = LocalDateTime.parse("2024-05-06T14:02:22.214");
java.sql.Date expectedSqlDate = java.sql.Date.valueOf("2024-05-06");
java.sql.Date sqlDate = java.sql.Date.valueOf(givenLocalDateTime.toLocalDate());
assertThat(sqlDate).isEqualTo(expectedSqlDate);
}
📌 这里要注意:时间部分会被丢弃!
5. 总结
在这篇文章中,我们介绍了两种常用的日期转换方式:
- ✅ 直接使用
Date.valueOf()
和toLocalDate()
进行手动转换 - ✅ 使用
AttributeConverter
实现自动转换,提升代码整洁度
同时也演示了如何将 LocalDateTime
转换为 java.sql.Date
,适用于只需要日期部分的场景。
完整代码可以在这里找到 👉 GitHub 项目地址
📌 踩坑提示:
- 不要试图直接把
LocalDateTime
塞进java.sql.Date
,会出问题 ❌ - 使用
AttributeConverter
时,注意是否真的需要全局生效(autoApply = true
)⚠️