Java 中 java.util.Date 与 java.sql.Date 有什么区别?
mhr18 2025-07-08 20:55 4 浏览 0 评论
Java 里的 java.util.Date 和 java.sql.Date 绝对是那种看起来不起眼但能搞得你 Debug 到半夜的“坑王”。
我们先从表面上看,java.sql.Date 是继承自 java.util.Date 的,按理说是“子承父业”,兼容没问题对吧?但实际上,这俩压根儿不是一个世界的。java.util.Date 是 Java 标准库里提供的“通用型”时间类,而 java.sql.Date 则是 JDBC 里为了数据库操作特化出来的版本,核心区别就在于:一个有时间,一个没时间!
就是这么沙雕的区别,java.sql.Date 把时间部分(小时、分钟、秒)全都砍了个干净,只保留年月日。为什么这么干?因为很多数据库的 DATE 类型本来就只存年月日,比如 MySQL 的 DATE 字段。所以 java.sql.Date 就跟着这个“传统艺能”走了,给你个精确到天的“日子”。
来看段代码你就明白了:
public class DateExample {
public static void main(String[] args) {
java.util.Date utilDate = new java.util.Date();
java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
System.out.println("utilDate: " + utilDate); // 有时间
System.out.println("sqlDate: " + sqlDate); // 只有年月日
}
}
输出可能是这样的:
utilDate: Thu Jun 05 15:30:12 CST 2025
sqlDate: 2025-06-05
你看,时间部分直接没了!这就导致很多时候你把 java.sql.Date 传回前端,前端一看没时间,直接懵了...
我遇到过最离谱的是,有个哥们把 java.sql.Date 强转成 java.util.Date,然后还奇怪为啥结果有问题。讲真,这是个巨坑。虽然它们在继承关系上确实可以强转,但你转完之后,它的“灵魂”还是那个没有时间的 sql.Date
所以你如果真的要拿 java.sql.Date 去做一些带时间的运算,比如和当前时间比较,或者转换成时间戳,那基本就是拿刀割自己手指头。比如这个例子:
java.sql.Date sqlDate = java.sql.Date.valueOf("2025-06-05");
long millis = sqlDate.getTime(); // 你以为这是某个时间点?
Date converted = new Date(millis);
System.out.println(converted); // 时间是 00:00:00 啊兄弟!
你以为你得到了“某一天的某个时刻”,结果其实是“那天的零点”... 这还不如直接用 LocalDate 呢。
对,说到这个就得扯一下 Java 8 的时间新 API——java.time.*。这波更新真的可以说是“Date 的反攻”。像 LocalDate 和 LocalDateTime 就分别对应 java.sql.Date 和 java.util.Date 的干净替代品,前者精确到天,后者精确到秒,而且线程安全,没有时区困扰,API 超清晰,看着就让人舒服。
LocalDate localDate = LocalDate.now();
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("LocalDate: " + localDate); // 2025-06-05
System.out.println("LocalDateTime: " + localDateTime); // 2025-06-05T15:45:30
最重要的是,java.sql.Date、java.sql.Time 和 java.sql.Timestamp 都有对应的 toLocalDate() 或 toLocalDateTime() 方法,基本可以无痛迁移。
但你要说现实项目里能不能彻底抛弃 java.sql.Date?我只能说:想多了。只要你在用 JDBC,尤其是用 MyBatis 或 Hibernate 这种 ORM 框架,它们底层还是会默认你搞点 java.sql.Date 出来。所以我个人的策略是:入库出库都用 LocalDate / LocalDateTime,中间统一转换。
比如用 MyBatis 的 TypeHandler 机制,写一个 LocalDate 转 java.sql.Date 的 Handler:
@MappedTypes(LocalDate.class)
public class LocalDateTypeHandler extends BaseTypeHandler<LocalDate> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
LocalDate parameter, JdbcType jdbcType) throws SQLException {
ps.setDate(i, Date.valueOf(parameter));
}
@Override
public LocalDate getNullableResult(ResultSet rs, String columnName) throws SQLException {
Date date = rs.getDate(columnName);
return date != null ? date.toLocalDate() : null;
}
// 其他两个 get 方法略
}
配上 XML 或注解,就能实现 LocalDate 的透明持久化,再也不用在每个 Entity 里扔一堆类型转换的代码了
另外顺带一提,还有不少人会问:“那 java.sql.Timestamp 是啥角色?”很简单,它就是 java.util.Date + 纳秒精度的变种,主要是数据库里有精确到秒甚至微秒的 TIMESTAMP 字段时用的。但我一般都尽量避免用它,因为那玩意儿坑更多,特别是跨数据库还经常有精度兼容性问题(MySQL 精确到毫秒,Oracle 精确到纳秒,一导出 CSV 就炸了...)
回到最初的问题:到底 java.util.Date 和 java.sql.Date 有啥区别?
如果用一句话总结就是:
java.util.Date 是全能选手,啥时间信息都有; java.sql.Date 是简化版,为了和数据库的 DATE 类型打配合,砍掉了时间部分,只保留“日期”。
但这区别,常常在你不注意的时候就搞事,所以我现在干脆上来就用 LocalDate 和 LocalDateTime,实在不行中间过渡一下,也总比在项目上线前踩坑强
相关推荐
- Springboot数据访问(整合动态数据源)
-
Springboot整合动态数据源dynamic-datasource-spring-boot-starter基本概念这个依赖是MyBatis-Plus团队开发的动态数据源组件,它是一个基于Spri...
- 《有手就会写sql》-第1章 数据库(sql实时更新同表里某个字段的数据)
-
为啥要用数据库存放数据的方式,有很多种,常用的比如:excel,数据库等。有了excel,为啥还要用数据库呢?原因有很多。其中之一:excel存储的数据有限的,最多能存个几千万条。但一个银行的交易数据...
- DBdoctor:一款企业级数据库性能诊断工具
-
DBdoctor是一个全面覆盖开发、测试、运维等各个环节SQL审核以及数据库性能诊断与优化的监控平台。针对数据库性能诊断门槛高、耗时长的问题,DBdoctor提供了快速易用的解决方案,深入到数...
- 面试必问:MySQL死锁 是什么,如何解决?(史上最全)
-
MySQL死锁接触少,但面试又经常被问到怎么办?最近有小伙伴在面试的时候,被问了MySQL死锁,如何解决?虽然也回答出来了,但是不够全面体系化,所以,小北给大家做一下系统化、体系化的梳理,帮助大家在面...
- JAVA入门教程-第1章 概述(java入门篇)
-
大道至简-JAVA入门教程在本教程中,你将学习Java语言的基础知识。Java基础内容涵盖:Java基础概念、Java词法结构、Java数组、Java流程控制、Java字符串、Java...
- 突发消息!微软停止俄罗斯业务(微软停止服务怎么办)
-
越来越多的IT公司加入封杀俄罗斯的阵营中。数字化转型网先后关注的有(点击下方蓝字可打开文章):SAP停止俄罗斯所有业务乌克兰呼吁SAP、Oracle封杀俄罗斯,Oracle已停止在俄所有业务埃森哲停止...
- 分布式数据库设计——存储引擎原理(全)
-
摘要数据库的一个首要目标是可靠并高效地管理数据,以供人们使用。进而不同的应用可以使用相同的数据库来共享它们的数据。数据库的出现使人们放弃了为每个独立的应用开发数据存储的想法,同时,随着数据库广泛的使用...
- Java运行环境配置(java运行环境配置成功截图)
-
若要在计算机上运行Java程序,需要配置Java运行环境(JRE)或Java开发工具包(JDK)。以下是在Windows操作系统上配置Java运行环境的步骤:下载Java安装程序:前往Oracle官方...
- 分布式任务调度Celery(分布式任务调度平台)
-
本文介绍了分布式任务调度系统Celery,包括安装,开发使用,并且配合supervisor,flower等工具进行系统化部署和使用。(一)安装和代码开发使用示例一,简介Celery是一个分布式任务调度...
- Android SDK 安装与配置(android sdk安装在哪里)
-
AndroidSDK安装与配置全流程指南一、前期准备与环境要求1.系统兼容性验证o操作系统:支持Windows10/11(64位)、macOS10.14+、Ubuntu16.04+等主流...
- 高性能Linux服务器构建实战:运维监控、性能调优与集群应用
-
百万级字迹详解实战案例,篇幅因素故只展现pdf目录,完整解析获取方式在篇尾了!目录读者对象Web应用篇(1至第3章)数据备份恢复篇(4至第6章)网络存储应用篇(7和第8章)运维监控与性能优化篇(9和第...
- Vmware虚拟机迁移数据库时踩过的坑
-
从Vmware迁移数据库虚拟机到其他平台,起来后认不到asm盘,不禁傻眼了。很多时候为了保证虚拟机系统的完整可启动,在做任何变更前,领导都会要求克隆一份镜像保存,或者直接在镜像上操作。这是传统的备份理...
- Java 中 java.util.Date 与 java.sql.Date 有什么区别?
-
Java里的java.util.Date和java.sql.Date绝对是那种看起来不起眼但能搞得你Debug到半夜的“坑王”。我们先从表面上看,java.sql.Date是继承自j...
- 主流数据库的不同点在哪?MySQL和SQL Server的区别介绍
-
在本教程中,树懒君介绍了两种最普遍应用的RDBMS—MySQL和MicrosoftSQLServer。通过介绍MySQL和SQLServer的几个关键区别,希望大家能在这两者之间做出最适合自己的...
- Java安全-Java Vuls(Fastjson、Weblogic漏洞复现)
-
复现几个Java的漏洞,文章会分多篇这是第一篇,文章会分组件和中间件两个角度进行漏洞复现复现使用环境VulhubVulFocus组件Fastjson1.2.24反序列化RCEFastJson...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (74)
- oracle批量插入数据 (65)
- oracle事务隔离级别 (59)
- oracle 空为0 (51)
- oracle主从同步 (56)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)