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
  • 理由
    1. MySQL 的 datetime 存储的是 YYYY-MM-DD HH:MM:SS 格式
    2. 不包含时区信息
    3. LocalDateTime 完全匹配这个特性

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. 总结建议

  1. 新项目一律使用 LocalDateTime
  2. 对应 MySQL datetime 时,优先用 LocalDateTime
  3. 如果数据库是 timestamp 类型,考虑用 Instant
  4. 只有在维护旧系统时才用 Date
  5. Java 8+ 环境下,避免使用任何 java.util.Date

简单记法:MySQL datetime = Java LocalDateTime

posted @ 2026-01-21 11:14  棠仔517890027  阅读(10)  评论(0)    收藏  举报