Java类初始化失败:NoClassDefFoundError排查与解决
线上出现NoClassDefFoundError: Could not initialize class时的排查思路和常见原因
支持通配符SSL证书、多域名证书、IP证书。适配ACME接口, 支持Zerossl、Let's Encrypt和Google等渠道。登录已有账号
2026-05-24 08:04:45 MySQL datetime 时间处理 Java
最近帮同事查一个订单创建时间丢时分秒的 bug,代码里明明设了 14:30:45,落库后变成 2024-05-20 00:00:00。
最后发现 ORM 映射里把字段写成了 java.sql.Date——这个坑我自己也踩过不止一次,刚好趁这次把 datetime 相关的常用操作和容易出问题的地方整理一下。
先看建表。需要记录完整时间点的时候,字段类型就设成 DATETIME,格式是 YYYY-MM-DD HH:MM:SS,范围从 1000-01-01 00:00:00 到 9999-12-31 23:59:59。
跟 date(只有日期)和 time(只有时间)的区别就在这里。
CREATE TABLE t_order (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
order_no VARCHAR(50) NOT NULL,
create_time DATETIME NOT NULL COMMENT '创建时间(含时分秒)'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
往这个字段里插数据,最省事的办法就是 NOW(),自动拿当前日期时间,带全时分秒:
INSERT INTO t_order (order_no, create_time)
VALUES ('ORD2024052001', NOW());
如果要插一个指定的时间,直接写标准格式的字符串就行,MySQL 会自动把它转成 datetime,不需要在外面多套一层 DATE_FORMAT:
INSERT INTO t_order (order_no, create_time)
VALUES ('ORD2024052003', '2024-05-20 14:30:45');
除非你的时间字符串格式比较怪,比如先拿到的是一串数字或非标准分隔符,那可以用 DATE_FORMAT 转一下:
INSERT INTO t_order (order_no, create_time)
VALUES ('ORD2024052002', DATE_FORMAT('2024-05-20 14:30:45', '%Y-%m-%d %H:%i:%s'));
不过多数情况下第一种就够了。另外,如果希望插入时自动填当前时间,定义字段的时候加上 DEFAULT CURRENT_TIMESTAMP,之后 INSERT 语句可以省掉这个字段:
CREATE TABLE t_order (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
order_no VARCHAR(50) NOT NULL,
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO t_order (order_no) VALUES ('ORD2024052004');
查询出来就是完整的 2024-05-20 14:30:45 格式,没啥特别的。想定制显示的话,用 DATE_FORMAT:
SELECT
order_no,
DATE_FORMAT(create_time, '%Y年%m月%d日 %H时%i分%s秒') AS formatted_time
FROM t_order;
单拿小时、分钟、秒可以用 HOUR()、MINUTE()、SECOND():
SELECT
order_no,
HOUR(create_time) AS hour,
MINUTE(create_time) AS minute,
SECOND(create_time) AS second
FROM t_order;
不过这些都是 SQL 层面的事。
真正容易出问题的,其实是应用代码跟数据库之间的类型映射。开头说的那种问题,在 Java 里的标准修法是这样——如果你用的是 Java 8 以上,直接用 java.time.LocalDateTime,通过 JDBC 驱动的 setObject 传进去就行:
LocalDateTime createTime = LocalDateTime.of(2024, 5, 20, 14, 30, 45);
ps.setObject(2, createTime);
还在用旧版本 Java 的话,就改用 java.sql.Timestamp:
Timestamp timestamp = Timestamp.valueOf("2024-05-20 14:30:45");
ps.setTimestamp(2, timestamp);
千万别用 java.sql.Date,那个只有日期部分,时分秒会全丢。
另一个高频问题是时区。Java 里明明时间是对的,进到库就少了 8 小时,或者多了。
这种情况大概率是 JVM 跟 MySQL 的时区没对齐。可以在 MySQL 那边设东八区:
SET GLOBAL time_zone = '+8:00';
SET SESSION time_zone = '+8:00';
或者在 JDBC 连接串里显式指定,这个更常用:
jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=Asia/Shanghai
实际项目里,我习惯把这几个点统一处理:数据库字段就用 DATETIME,Java 侧固定用 LocalDateTime,连接串带上 serverTimezone=Asia/Shanghai,SQL 一律参数绑定不拼字符串。这样类型映射和时区一般不会再折腾你。需要范围查询的 datetime 字段,比如按时间段拉订单,该加索引就加一个:
CREATE INDEX idx_create_time ON t_order(create_time);
基本就这些。时间类型出的问题排查起来往往很绕,但最后发现都落在类型映射和时区配置上,提前统一掉能省很多半夜报警。
上一篇: Ubuntu 下动态链接库路径的折腾记录
线上出现NoClassDefFoundError: Could not initialize class时的排查思路和常见原因
聊聊CASE WHEN的两种语法、典型场景,以及类型、NULL、性能上那些线上跑起来才会注意到的问题。
记录一次排序 NPE 的排查和解决,顺便说下 IDEA 调试集合时 null 元素不显示的问题怎么调整。
跑单测突然报 Command line is too long,大多数情况在 Run Configuration 里勾一个选项就完事。这里把原因和几种方案一起记一下。
在处理海量MySQL数据时,如何高效利用REPLACE函数进行字符串替换,避免性能瓶颈?本文不仅详述REPLACE的强大功能,更聚焦于其在大型数据库操作中的性能表现与优化技巧。我们将深入探讨分批执行、索引影响、事务管理等高级策略,旨在帮助DBA和开发者在实现数据清洗、格式统一的同时,最大限度保障系统性能,确保数据操作的顺畅与高效。