LocalDateTime和 Date
问题
java中 LocalDateTime 和 Date 的区别,mysql中使用了datetime,java中应该使用什么?
1. 核心区别
Date (java.util.Date 和 java.sql.Date)
- 设计年代:Java 1.0 引入,API 设计存在缺陷
- 时区问题:内部存储的是 UTC 时间戳,但很多方法(如
toString(),getYear())使用默认时区 - 可变性:对象是可变的,线程不安全
- API 混乱:大部分方法已废弃(@Deprecated)
LocalDateTime (java.time 包)
- Java 8+ 引入,基于 Joda-Time 设计
- 不可变:线程安全
- 不包含时区:只表示本地日期时间
- 清晰的 API:丰富的日期时间操作方法
- 与时区分离:需要时区时用 ZonedDateTime
2. 对比表格
| 特性 | Date | LocalDateTime |
|---|---|---|
| 设计质量 | 较差,有历史包袱 | 优秀,现代设计 |
| 线程安全 | 否(可变对象) | 是(不可变对象) |
| 时区处理 | 隐式(易出错) | 显式(与 ZoneId 分离) |
| API 易用性 | 较差 | 优秀 |
| 推荐度 | 不推荐新项目使用 | 推荐使用 |
3. MySQL 与 Java 类型映射
对于 MySQL 的 datetime
- 最佳选择:
LocalDateTime - 理由:
- MySQL 的 datetime 存储的是
YYYY-MM-DD HH:MM:SS格式 - 不包含时区信息
LocalDateTime完全匹配这个特性
- MySQL 的 datetime 存储的是
JDBC 映射示例
// 写入数据库
LocalDateTime now = LocalDateTime.now();
PreparedStatement stmt = conn.prepareStatement(
"INSERT INTO table (created_at) VALUES (?)"
);
stmt.setObject(1, now); // 直接使用 LocalDateTime
// 从数据库读取
ResultSet rs = stmt.executeQuery("SELECT created_at FROM table");
while (rs.next()) {
LocalDateTime dt = rs.getObject("created_at", LocalDateTime.class);
// 或者
// LocalDateTime dt = rs.getTimestamp("created_at").toLocalDateTime();
}
4. 完整场景建议
场景 1:简单业务时间戳
// ✅ 推荐
@Column(name = "created_at")
private LocalDateTime createdAt;
// ❌ 避免
@Column(name = "created_at")
private Date createdAt; // 旧API
场景 2:需要考虑时区
// 如果 MySQL 用 timestamp 类型(带时区)
@Column(name = "updated_at")
private Instant updatedAt; // 存储 UTC 时间戳
// 或者在 Java 层面处理时区
LocalDateTime localTime = LocalDateTime.now();
ZonedDateTime zonedTime = localTime.atZone(ZoneId.of("Asia/Shanghai"));
场景 3:与旧代码兼容
// 如果需要和旧 Date API 互操作
LocalDateTime ldt = LocalDateTime.now();
Date date = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
// Date 转 LocalDateTime
Date oldDate = new Date();
LocalDateTime newLdt = oldDate.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
5. 实体类示例
@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "order_no")
private String orderNo;
// ✅ 使用 LocalDateTime
@Column(name = "create_time")
private LocalDateTime createTime;
@Column(name = "update_time")
private LocalDateTime updateTime;
// 使用 JPA 自动设置时间
@PrePersist
protected void onCreate() {
createTime = LocalDateTime.now();
}
@PreUpdate
protected void onUpdate() {
updateTime = LocalDateTime.now();
}
// getters and setters
}
6. 总结建议
- 新项目一律使用
LocalDateTime - 对应 MySQL datetime 时,优先用
LocalDateTime - 如果数据库是 timestamp 类型,考虑用
Instant - 只有在维护旧系统时才用
Date - Java 8+ 环境下,避免使用任何
java.util.Date
简单记法:MySQL datetime = Java LocalDateTime

浙公网安备 33010602011771号