resultset读取null时,基本类型getxxx()会返回默认值(如0、false)而非null,导致逻辑错误;正确做法是用包装类型+wasnull()判断,或jdbc 4.2+推荐getobject(col, type.class)自动处理null。

Java 中 JDBC 从 MySQL 查询结果中读取 NULL 值时,若直接用 ResultSet.getXXX() 方法映射到基本数据类型(如 int、boolean、double),会抛出 SQLException 或返回默认值(如 0、false),造成逻辑错误。根本原因是:**基本类型不能为 null,而数据库字段可以为 NULL**。正确做法是优先使用对应的包装类型 + 显式空值检查。
用包装类型替代基本类型,并配合 wasNull() 判断
MySQL 的 INT NULL 字段应映射为 Integer,而非 int;TINYINT(1) 表示布尔时对应 Boolean,而非 boolean。JDBC 驱动对包装类型的 getXXX() 方法在遇到 NULL 时返回 null,但需调用 wasNull() 确认是否真为数据库 NULL(部分驱动在返回 null 后自动设标志,但规范写法仍建议检查):
Integer id = rs.getInt("id"); if (rs.wasNull()) id = null;Boolean active = rs.getBoolean("is_active"); if (rs.wasNull()) active = null;Double price = rs.getDouble("price"); if (rs.wasNull()) price = null;
避免直接用基本类型 getXXX() 方法读取可能为 NULL 的列
像 rs.getInt("age") 这类调用,当数据库值为 NULL 时,MySQL Connector/J 默认返回 0(不是异常),极易掩盖真实空值。这不是 bug,而是 JDBC 规范允许的“默认行为”,但业务上往往不可接受。务必禁止此类写法,除非你明确知道该字段非空且需要默认值。
- ❌ 错误:
int age = rs.getInt("age"); // NULL → 0,丢失语义 - ✅ 正确:
Integer age = rs.getInt("age"); if (rs.wasNull()) age = null;或直接用getObject("age", Integer.class)
推荐使用 getObject() + 类型参数(JDBC 4.2+)
JDBC 4.2 引入了泛型 ResultSet.getObject(String columnLabel, Class<t> type)</t>,它能自动处理 NULL 并返回对应包装类型的 null,无需手动调用 wasNull(),代码更简洁安全:
Integer id = rs.getObject("id", Integer.class); // NULL → nullLocalDateTime createdAt = rs.getObject("created_at", LocalDateTime.class);Boolean deleted = rs.getObject("deleted", Boolean.class);
注意:确保使用的 MySQL 驱动版本 ≥ 8.0(推荐 8.0.33+),并启用 useLegacyDatetimeCode=false 等现代配置以保障时间类型兼容性。
ORM 框架中的常见处理(补充参考)
MyBatis、Hibernate 等框架内部已封装上述逻辑。例如 MyBatis 的 <result></result> 映射到 java.lang.Integer 字段时,自动将 NULL 转为 null;Hibernate 实体用 Integer 对应 @Column(nullable = true) 字段也天然支持。但手写 JDBC 时,必须自行承担空值判断责任。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











