Java日期格式化之IllegalArgumentException与MySQL数据截断问题解决
作者:码农阿豪@新空间
引言
在Java开发中,日期时间处理和数据库字段映射是常见的任务,但也容易遇到各种问题,例如:
IllegalArgumentException: Cannot format given Object as a Date(日期格式化失败)- MySQL
Data truncated for column(数据截断错误)
本文将通过实际案例,分析这些问题的根本原因,并提供最佳实践解决方案,涵盖:
- Java日期时间格式化问题(
LocalDateTimevsDate) - MySQL字段长度与数据截断问题
- 代码优化与统一处理方案
一、Java日期格式化问题:IllegalArgumentException
1.1 问题现象
在导出Excel时,以下代码抛出异常:
row.createCell(15).setCellValue(
order.getProcessTime() != null ?
dateFormat.format(order.getProcessTime()) :
""
);
报错信息:
java.lang.IllegalArgumentException: Cannot format given Object as a Date
原因是 order.getProcessTime() 返回的是 LocalDateTime,但 dateFormat(SimpleDateFormat)只能处理 java.util.Date 类型。
1.2 根本原因
SimpleDateFormat仅支持Date类型,不能直接格式化LocalDateTime、Timestamp等。- Java 8+ 推荐使用
java.time包(如LocalDateTime),但旧代码可能仍依赖Date。
1.3 解决方案
方案1:转换为Date再格式化(兼容旧代码)
if (order.getProcessTime() != null) {
Date date = Date.from(
order.getProcessTime().atZone(ZoneId.systemDefault()).toInstant()
);
row.createCell(15).setCellValue(dateFormat.format(date));
} else {
row.createCell(15).setCellValue("");
}
方案2:直接使用DateTimeFormatter(推荐)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
row.createCell(15).setCellValue(
order.getProcessTime() != null ?
order.getProcessTime().format(formatter) :
""
);
方案3:提取工具类(统一处理)
public class DateUtils {
private static final DateTimeFormatter DEFAULT_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static String format(LocalDateTime dateTime) {
return dateTime != null ? dateTime.format(DEFAULT_FORMATTER) : "";
}
}
// 调用
row.createCell(15).setCellValue(DateUtils.format(order.getProcessTime()));
二、MySQL数据截断问题:Data truncated for column
2.1 问题现象
插入数据时报错:
(pymysql.err.DataError) (1265, "Data truncated for column 'match_status' at row 1")
SQL日志:
INSERT INTO customer_order (..., match_status, ...) VALUES (..., '待匹配', ...)
原因是 match_status 列的长度不足以存储 "待匹配"(3个字符)。
2.2 根本原因
MySQL字段定义可能是 VARCHAR(2) 或 ENUM,但插入了更长的值。
例如:
VARCHAR(2)无法存储"待匹配"(3字符)。ENUM('匹配', '不匹配')无法接受"待匹配"。
2.3 解决方案
步骤1:检查表结构
DESCRIBE customer_order;
重点关注 match_status 的类型:
如果是 VARCHAR(2),需要扩展长度:
ALTER TABLE customer_order MODIFY COLUMN match_status VARCHAR(10);
如果是 ENUM,需要添加选项:
ALTER TABLE customer_order MODIFY COLUMN match_status ENUM('匹配', '待匹配', '不匹配');
步骤2:验证数据长度
在Java代码中检查字段长度:
if (order.getMatchStatus().length() > 10) {
throw new IllegalArgumentException("match_status 超出长度限制");
}
步骤3:统一处理(推荐)
public class DbUtils {
public static void validateOrder(CustomerOrder order) {
if (order.getMatchStatus() != null && order.getMatchStatus().length() > 10) {
throw new IllegalArgumentException("match_status 超出长度限制");
}
}
}
// 调用
DbUtils.validateOrder(order);
db.insert(order);
三、完整优化代码示例
3.1 日期时间格式化工具类
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public final class DateUtils {
private static final DateTimeFormatter DEFAULT_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static String format(LocalDateTime dateTime) {
return dateTime != null ? dateTime.format(DEFAULT_FORMATTER) : "";
}
}
3.2 数据库字段校验工具类
public final class DbUtils {
public static void validateOrder(CustomerOrder order) {
// 检查 match_status 长度
if (order.getMatchStatus() != null && order.getMatchStatus().length() > 10) {
throw new IllegalArgumentException("match_status 超出长度限制");
}
// 其他字段校验...
}
}
3.3 统一调用示例
// 1. 校验数据 DbUtils.validateOrder(order); // 2. 格式化日期 row.createCell(15).setCellValue(DateUtils.format(order.getProcessTime())); row.createCell(16).setCellValue(DateUtils.format(order.getCreateTime())); row.createCell(17).setCellValue(DateUtils.format(order.getUpdateTime())); // 3. 插入数据库 db.insert(order);
四、总结与最佳实践
4.1 日期时间处理
- 避免使用
SimpleDateFormat:线程不安全且仅支持Date。 - 推荐
DateTimeFormatter:支持LocalDateTime,线程安全。 - 提取工具类:统一格式化逻辑。
4.2 MySQL字段设计
- 提前规划字段长度:例如
VARCHAR(10)比VARCHAR(2)更灵活。 - 使用
ENUM约束取值:避免非法数据。 - 代码校验数据长度:提前拦截问题。
4.3 统一处理原则
- 减少重复代码:通过工具类复用逻辑。
- 提前校验:在插入数据库前检查数据合法性。
通过以上优化,可以彻底解决日期格式化和数据截断问题,提升代码健壮性!
到此这篇关于Java日期格式化之IllegalArgumentException与MySQL数据截断问题解决的文章就介绍到这了,更多相关Java日期格式化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
