- 核心类型映射表:最常用、最直接的对应关系。
- 详细说明与注意事项:对关键类型进行深入解释,特别是容易出错的地方。
- ORM 框架(如 MyBatis, JPA)的映射:现代开发中,我们通常使用框架,它们提供了更灵活的映射方式。
- 总结与最佳实践。
核心类型映射表
这是一个快速参考表,涵盖了最常用的场景。

| MySQL 数据类型 | Java 数据类型 (JDBC) | Java 数据类型 (JPA / MyBatis) | 备注 |
|---|---|---|---|
| 数值类型 | |||
TINYINT |
java.lang.Byte |
Byte, Integer |
TINYINT(1) 常用作布尔值,对应 java.lang.Boolean |
SMALLINT |
java.lang.Short |
Short, Integer |
|
INT, INTEGER |
java.lang.Integer |
Integer |
最常用的整数类型 |
BIGINT |
java.lang.Long |
Long |
用于主键、自增ID、时间戳等大数 |
FLOAT |
java.lang.Float |
Float |
单精度浮点数,注意精度问题 |
DOUBLE |
java.lang.Double |
Double |
双精度浮点数,比 FLOAT 精度高 |
DECIMAL |
java.math.BigDecimal |
BigDecimal |
用于精确计算,如货币、财务数据。强烈推荐 |
| 字符串类型 | |||
CHAR |
java.lang.String |
String |
定长字符串 |
VARCHAR |
java.lang.String |
String |
变长字符串,最常用的文本类型 |
TEXT |
java.lang.String |
String, Lob |
大文本,JPA 中常用 @Lob 注解,类型为 String 或 byte[] |
| 日期时间类型 | |||
DATE |
java.sql.Date |
java.time.LocalDate |
仅存储日期(年-月-日) |
TIME |
java.sql.Time |
java.time.LocalTime |
仅存储时间(时:分:秒) |
DATETIME |
java.sql.Timestamp |
java.time.LocalDateTime |
存储日期和时间(年-月-日 时:分:秒) |
TIMESTAMP |
java.sql.Timestamp |
java.time.Instant, java.time.LocalDateTime |
存储日期和时间,且受时区影响。TIMESTAMP 范围较小,但会自动转换时区 |
| 二进制类型 | |||
BLOB |
byte[] |
byte[], @Lob |
二进制大对象,如图片、文件等,JPA 中用 @Lob 注解 |
BIT |
java.lang.Boolean 或 byte[] |
Boolean |
BIT(1) 对应 Boolean,多位 BIT 对应 byte[] |
详细说明与注意事项
数值类型
TINYINT和布尔值:- 在 MySQL 中,
TINYINT(1)经常被用作布尔值,0代表false,非0代表true。 - 在 Java 中,最自然的映射是
java.lang.Boolean,JPA 的@Column(columnDefinition = "TINYINT(1)")可以很好地处理这一点。
- 在 MySQL 中,
DECIMALvsFLOAT/DOUBLE:- 这是最常见也最容易出错的映射点。
FLOAT和DOUBLE是浮点数,遵循 IEEE 754 标准,在计算机中是以二进制存储的,因此无法精确表示某些十进制小数。1 + 0.2在浮点数计算中可能不等于3。DECIMAL是定点数,它以字符串形式存储数值,可以精确表示小数。所有涉及金钱、财务、科学计算等对精度要求高的场景,都必须使用DECIMAL,并在 Java 中映射为java.math.BigDecimal。- 注意:在 JDBC 中,从
DECIMAL读取数据时,使用getBigDecimal()方法,如果错误地使用getDouble(),会丢失精度。
字符串类型
CHARvsVARCHAR:CHAR是定长,如果存入的字符串长度不足,会用空格补齐。VARCHAR是变长,只存实际字符。- 在 Java 中,两者都映射为
String,区别在于 MySQL 端的处理逻辑,Java 代码无需区分。
日期时间类型
- 这是另一个极易出错的领域,主要涉及
java.util.Date、java.sql.Date、java.sql.Timestamp和 Java 8 的新时间 API。 - *JDBC 旧 API (`java.sql.`)**:
java.sql.Date: 对应 MySQL 的DATE,它只包含日期信息,没有时间部分。new java.sql.Date(date.getTime())可以从java.util.Date转换。java.sql.Time: 对应 MySQL 的TIME,只包含时间信息。java.sql.Timestamp: 对应 MySQL 的DATETIME和TIMESTAMP,它同时包含日期和时间信息,精度到纳秒。在 JDBC 中,处理DATETIME和TIMESTAMP通常使用getTimestamp()和setTimestamp()。
- *Java 8 新时间 API (`java.time.`)强烈推荐使用**
LocalDate: 对应java.sql.Date和 MySQL 的DATE,表示一个不可变的日期。LocalTime: 对应java.sql.Time和 MySQL 的TIME,表示一个不可变的时间。LocalDateTime: 对应java.sql.Timestamp和 MySQL 的DATETIME,表示一个不可变的日期和时间。Instant: 对应 MySQL 的TIMESTAMP,它表示一个时间线上的瞬时点,不与时区关联,非常适合存储和传输时间戳。
- 时区问题:
DATETIME不存储时区信息,它存储的是“本地时间”。TIMESTAMP会存储 UTC 时间,并在读取和写入时根据服务器的时区进行转换。- 最佳实践:如果应用需要支持全球用户,建议所有数据库字段都使用
TIMESTAMP,或者在应用层面统一使用 UTC 时间,然后在展示时再转换为用户所在时区的时间。
ORM 框架的映射
在现代开发中,我们很少直接使用 JDBC,而是使用 ORM(对象关系映射)框架,如 JPA(Hibernate 实现)或 MyBatis。
JPA (Java Persistence API)
JPA 通过注解来定义 Java 对象与数据库表的映射关系。
示例:一个用户实体类
import javax.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalDate;
@Entity // 声明这是一个JPA实体
@Table(name = "t_user") // 对应数据库中的 t_user 表
public class User {
@Id // 声明这是主键
@GeneratedValue(strategy = GenerationType.IDENTITY) // 自增主键
private Long id;
@Column(nullable = false, length = 50) // 对应 VARCHAR(50)
private String username;
@Column(columnDefinition = "TINYINT(1)") // 显式指定列类型
private Boolean isActive;
@Column(name = "balance", precision = 10, scale = 2) // 对应 DECIMAL(10, 2)
private BigDecimal balance;
@Column(name = "birth_date") // 对应 DATE
private LocalDate birthDate;
@Column(name = "created_at") // 对应 DATETIME
private LocalDateTime createdAt;
// Getters and Setters...
}
@Entity: 标记类为实体。@Table: 指定对应的数据库表。@Id: 标记主键。@GeneratedValue: 定义主键生成策略。@Column: 用于详细配置列属性,如name(列名)、nullable(是否可为空)、length(字符串长度)、precision和scale(用于DECIMAL)、columnDefinition(直接指定SQL列定义)。
MyBatis
MyBatis 的映射更灵活,通常在 XML 文件或注解中定义。

示例:Mapper XML
<mapper namespace="com.example.mapper.UserMapper">
<resultMap id="userResultMap" type="com.example.model.User">
<id property="id" column="id" />
<result property="username" column="username" jdbcType="VARCHAR" />
<result property="isActive" column="is_active" jdbcType="BIT" />
<result property="balance" column="balance" jdbcType="DECIMAL" />
<result property="birthDate" column="birth_date" jdbcType="DATE" />
<result property="createdAt" column="created_at" jdbcType="TIMESTAMP" />
</resultMap>
<select id="selectById" resultMap="userResultMap">
SELECT id, username, is_active, balance, birth_date, created_at
FROM t_user
WHERE id = #{id}
</select>
</mapper>
- MyBatis 使用
resultMap来明确指定 Java 对象的属性如何与数据库的列对应。 jdbcType是可选的,但显式指定可以避免一些类型不匹配的问题,特别是在使用 语法时。
总结与最佳实践
- 优先使用 Java 8 的时间 API:
LocalDate,LocalTime,LocalDateTime比java.sql.Date和java.sql.Timestamp更现代、更易用,线程也更安全。 - 财务数据必须用
BigDecimal:对于所有货币和精确计算,MySQL 使用DECIMAL,Java 使用java.math.BigDecimal,避免使用float和double。 - 主键使用
BIGINT:即使当前数据量不大,也建议使用BIGINT作为自增主键,以应对未来业务增长,避免INT溢出。 - 利用 ORM 框架:使用 JPA 或 MyBatis 可以大大简化数据类型映射的工作,提高开发效率和代码可维护性,在定义实体时,明确注解列的类型和约束。
- 注意时区:如果你的应用是面向全球用户的,请统一使用 UTC 时间进行存储和计算,并在前端或业务逻辑层进行时区转换。
- 保持一致性:在一个项目中,尽量保持数据类型映射的规范和一致性,约定所有日期时间字段都使用
TIMESTAMP并映射为LocalDateTime。

