- MySQL (SQL):基于关系模型,数据类型是面向存储和计算的,如
INT用于整数,VARCHAR用于字符串。 - Java (OOP):基于面向对象模型,数据类型是面向对象的,如
Integer是一个对象,可以包含null值;int是一个基本数据类型,不能为null。
映射的核心就是如何将 MySQL 的关系型数据转换为 Java 的对象或基本类型。

核心映射原则
- JDBC 是桥梁:Java 通过 JDBC (Java Database Connectivity) API 与 MySQL 交互,JDBC 提供了一套标准的类型转换规则,这是最权威的映射依据。
ResultSet的获取方法:在 JDBC 中,你调用的ResultSet的getXXX()方法(如getInt(),getString())决定了数据如何从 MySQL 类型转换为 Java 类型。PreparedStatement的设置方法:同样,你调用的PreparedStatement的setXXX()方法决定了 Java 类型如何转换为 MySQL 类型。NULL值的处理:这是最容易出错的地方,如果你希望一个数据库字段可以为NULL,那么在 Java 中,必须使用对应的包装类(Wrapper Class),而不是基本类型,数据库的INT字段可以为NULL,Java 中就应该用Integer而不是int。
常用数据类型映射对照表
下面是一个详细的、按功能分类的对照表,包含了 MySQL 类型、推荐 Java 类型、JDBC 方法以及重要说明。
| MySQL 类型 | 推荐的 Java 类型 (JDBC getXXX) |
JDBC getXXX 方法 |
JDBC setXXX 方法 |
重要说明 |
|---|---|---|---|---|
| 整数类型 | ||||
TINYINT(1) |
boolean / Boolean |
getBoolean() |
setBoolean() |
通常用于布尔值。0 是 false,非 0 是 true。 |
TINYINT |
byte / Byte |
getByte() |
setByte() |
8位有符号整数,范围 -128 到 127。 |
SMALLINT |
short / Short |
getShort() |
setShort() |
16位有符号整数。 |
INT, INTEGER |
int / Integer |
getInt() |
setInt() |
最常用,32位有符号整数,可为 NULL 时用 Integer。 |
BIGINT |
long / Long |
getLong() |
setLong() |
64位有符号整数,常用于自增主键、时间戳等。 |
| 精确数值类型 | ||||
DECIMAL, NUMERIC |
java.math.BigDecimal |
getBigDecimal() |
setBigDecimal() |
用于精确计算,如货币、财务数据。强烈推荐,避免使用 float/double。 |
FLOAT |
float / Float |
getFloat() |
setFloat() |
单精度浮点数,不精确。 |
DOUBLE |
double / Double |
getDouble() |
setDouble() |
双精度浮点数,不精确,比 float 精度高,但仍不精确。 |
| 字符串类型 | ||||
CHAR, VARCHAR |
String |
getString() |
setString() |
最常用,处理文本数据。 |
TEXT (各种大小) |
String |
getString() / getCharacterStream() |
setString() / setCharacterStream() |
对于大文本,getString() 可能会因内存问题失败,推荐使用流式处理 getCharacterStream()。 |
ENUM |
String / enum (自定义) |
getString() |
setString() |
映射为 String,最佳实践是创建一个 Java enum 类来增强类型安全。 |
| 日期和时间类型 | ||||
DATE |
java.sql.Date |
getDate() |
setDate() |
仅包含日期 (年-月-日)。java.sql.Date 是 java.util.Date 的子类,但已被废弃,现代应用推荐 java.time.LocalDate。 |
TIME |
java.sql.Time |
getTime() |
setTime() |
仅包含时间 (时:分:秒),推荐 java.time.LocalTime。 |
DATETIME |
java.sql.Timestamp |
getTimestamp() |
setTimestamp() |
同时包含日期和时间,包含纳秒精度,推荐 java.time.LocalDateTime。 |
TIMESTAMP |
java.sql.Timestamp |
getTimestamp() |
setTimestamp() |
类似 DATETIME,但受时区影响,且范围更大,推荐 java.time.Instant。 |
| 二进制类型 | ||||
BLOB, BINARY, VARBINARY |
byte[] |
getBytes() |
setBytes() |
用于存储二进制数据,如图片、文件等,对于大 BLOB,推荐使用 getBinaryStream() 和 setBinaryStream() 以避免内存问题。 |
| 布尔类型 | ||||
BIT(1) |
boolean / Boolean |
getBoolean() |
setBoolean() |
与 TINYINT(1) 类似,但语义更明确。 |
Java 8+ java.time API 的现代映射
从 Java 8 开始,官方推荐使用 java.time 包中的类来替代旧的 java.sql.Date 和 java.util.Date,这些类更清晰、更不可变,并且线程安全。
| MySQL 类型 | 推荐的现代 Java 类型 | 转换方式 |
|---|---|---|
DATE |
java.time.LocalDate |
LocalDate date = resultSet.getObject("date_column", LocalDate.class); |
TIME |
java.time.LocalTime |
LocalTime time = resultSet.getObject("time_column", LocalTime.class); |
DATETIME |
java.time.LocalDateTime |
LocalDateTime dateTime = resultSet.getObject("datetime_column", LocalDateTime.class); |
TIMESTAMP |
java.time.Instant |
Instant instant = resultSet.getObject("timestamp_column", Instant.class); |
注意:要使用这种现代方式,你的 JDBC 驱动版本需要较新(MySQL Connector/J 8.0+ 支持),并且可能需要在连接字符串中添加 &useLegacyDatetimeCode=false 或 &serverTimezone=时区。
ORM 框架(如 MyBatis, JPA)中的映射
在使用 ORM (Object-Relational Mapping) 框架时,你通常不会直接操作 JDBC 方法,而是通过注解或 XML 配置来定义映射关系。

MyBatis 示例
MyBatis 会自动进行类型转换,但你也可以显式指定。
<!-- UserMapper.xml -->
<select id="selectUserById" resultType="com.example.User">
SELECT id, name, create_time FROM users WHERE id = #{id}
</select>
// User.java (POJO)
public class User {
private Integer id;
private String name;
// 使用 java.time.LocalDateTime
private LocalDateTime createTime;
// getters and setters...
}
MyBatis 会自动将 create_time (DATETIME) 列的值映射到 User 对象的 createTime (LocalDateTime) 字段上。
JPA / Hibernate 示例
JPA 使用注解来定义映射。
// User.java (Entity)
import javax.persistence.*;
import java.time.LocalDateTime;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
@Column(name = "create_time")
private LocalDateTime createTime; // JPA/Hibernate 会自动处理转换
// getters and setters...
}
JPA 提供供了 @Temporal 注解来处理旧版的日期时间类型,但对于 java.time,通常直接使用即可。
最佳实践总结
- 优先考虑可为
NULL的字段:如果数据库列允许NULL,在 Java 中务必使用包装类 (Integer,Double,Boolean,String),而不是基本类型 (int,double,boolean),这是避免NullPointerException的关键。 - 财务数据用
BigDecimal:所有涉及金钱、价格、金额的计算,都必须使用java.math.BigDecimal,绝对不要使用float或double,因为它们会引入精度误差。 - 拥抱
java.time:对于新的 Java 项目,强烈推荐使用java.time包中的LocalDate,LocalTime,LocalDateTime,Instant等类来处理日期和时间,它们比旧的 API 更好用。 - 大对象用流:对于
TEXT或BLOB等大字段,优先使用getCharacterStream()/setCharacterStream()或getBinaryStream()/setBinaryStream(),以避免一次性将大量数据加载到内存中。 - 明确映射,避免隐式转换:虽然 JDBC 和 ORM 框架能进行隐式类型转换,但最好在代码或配置中显式地指定类型,这样代码更清晰,也更容易排查问题,明确调用
getInt()而不是getObject()再强制转换。
掌握这些映射关系,能让你在开发数据库应用时更加得心应手,减少因类型不匹配导致的奇怪错误。
