从 MySQL 到 Java:字段类型对应全解析,避坑指南看这篇就够了​

作为一名 Java 开发者,你是否曾在调试时遇到过这样的报错:Data truncation: Out of range value for column 'age' at row 1?或者在查询数据时发现日期时间总是差 8 小时?又或者 Decimal 类型的数值在 Java 中计算时莫名丢失了精度?​

这些问题的根源,往往在于MySQL 字段类型与 Java 字段类型的映射关系处理不当。看似简单的 “类型对应”,实则藏着无数细节陷阱。无论是刚入行的新手还是资深开发者,稍有疏忽就可能踩坑,轻则导致数据异常,重则引发生产事故。​

本文将从基础到进阶,全面解析 MySQL 与 Java 的字段类型对应关系,结合 10 + 实战案例拆解常见问题,并附赠 ORM 框架(MyBatis/JPA)的映射技巧,帮你彻底搞定类型映射难题。​

一、为什么类型对应如此重要?​

在 Java 开发中,数据库交互是绕不开的环节。当我们用 JDBC 或 ORM 框架(如 MyBatis、JPA)操作 MySQL 时,数据会经历 “MySQL 字段→Java 对象” 或 “Java 对象→MySQL 字段” 的转换过程。这个过程中,类型映射的准确性直接决定了数据的完整性和正确性。​

举个简单的例子:如果 MySQL 字段是BIGINT(范围 - 9223372036854775808~9223372036854775807),而 Java 中用Integer(范围 - 2147483648~2147483647)接收,当数据库中存储的数值超过 2147483647 时,就会出现数据溢出,导致查询结果异常。​

再比如,MySQL 的DATETIME类型与 Java 的LocalDateTime映射时,如果忽略时区配置,可能会出现 “数据库存的是 2023-10-01 12:00,Java 查出来却是 2023-10-01 04:00” 的时区偏移问题。​

据统计,在数据库相关的生产事故中,类型映射不当导致的问题占比超过 35%。因此,掌握 MySQL 与 Java 的类型对应规则,是每个 Java 开发者的必备技能。​

二、基础类型对应:从数值到字符串的完美映射​

MySQL 的字段类型可分为数值型、字符串型、日期时间型三大类,这三类也是日常开发中最常用的。我们先从基础类型入手,逐个解析其对应的 Java 类型及注意事项。​

2.1 数值型:精度与范围的平衡术​

MySQL 的数值型字段分为整数和小数两大类,不同类型的存储范围和精度差异很大,对应的 Java 类型也需精准匹配。​

2.1.1 整数类型(TINYINT 到 BIGINT)​

MySQL 的整数类型按存储范围从小到大分为:TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,且支持UNSIGNED(无符号)属性。对应的 Java 类型需根据其范围选择,避免溢出。​

MySQL 类型​

存储范围(有符号)​

存储范围(无符号)​

推荐 Java 类型​

不推荐类型(原因)​

TINYINT​

-128 ~ 127​

0 ~ 255​

byte​

int(浪费空间)​

TINYINT UNSIGNED​

无(本身为无符号)​

0 ~ 255​

short​

byte(范围不足)​

SMALLINT​

-32768 ~ 32767​

0 ~ 65535​

short​

int(浪费空间)​

SMALLINT UNSIGNED​

无​

0 ~ 65535​

int​

short(范围不足)​

MEDIUMINT​

-8388608 ~ 8388607​

0 ~ 16777215​

int​

short(范围不足)​

INT​

-2147483648 ~ 2147483647​

0 ~ 4294967295​

int​

long(浪费空间)​

INT UNSIGNED​

无​

0 ~ 4294967295​

long​

int(范围不足,会溢出)​

BIGINT​

-9223372036854775808 ~ 9223372036854775807​

0 ~ 18446744073709551615​

long​

int(范围严重不足)​

BIGINT UNSIGNED​

无​

0 ~ 18446744073709551615​

BigInteger​

long(范围不足,会溢出)​

实战案例:INT UNSIGNED 的溢出陷阱​

假设 MySQL 表中有一个字段user_id定义为INT UNSIGNED,用于存储用户 ID(最大可存 4294967295)。如果 Java 实体类中用Integer接收:​

// 错误示例​

public class User {​

private Integer userId; // 对应MySQL的INT UNSIGNED​

// 其他字段...​

}​

当user_id的值超过 2147483647 时(比如 3000000000),查询时会直接抛出异常:​

java.sql.SQLException: Out of range value for column 'user_id'​

正确做法:用long接收INT UNSIGNED类型:​

// 正确示例​

public class User {​

private Long userId; // 对应MySQL的INT UNSIGNED​

// 其他字段...​

}​

2.1.2 小数类型(FLOAT、DOUBLE、DECIMAL)​

小数类型的核心问题是精度。MySQL 的FLOAT和DOUBLE是浮点型,存在精度丢失风险;DECIMAL是定点型,可精确存储小数,适合金额等敏感场景。​

MySQL 类型​

精度特点​

推荐 Java 类型​

适用场景​

FLOAT​

单精度,约 7 位有效数字​

float​

非精确计算(如温度、重量)​

DOUBLE​

双精度,约 15 位有效数字​

double​

较高精度但非精确场景​

DECIMAL(M,D)​

精确存储,M 为总位数,D 为小数位​

java.math.BigDecimal​

金额、汇率等精确计算场景​

实战案例:精度丢失的血泪教训​

假设用DOUBLE存储订单金额,MySQL 字段定义为amount DOUBLE(10,2),Java 用double接收:​

// 实体类​

public class Order {​

private double amount; // 对应DOUBLE(10,2)​

}​

// 插入数据:amount=9.99​

orderMapper.insert(new Order(9.99));​

// 查询后计算:9.99 * 3 = ?​

Order order = orderMapper.selectById(1);​

double result = order.getAmount() * 3; ​

System.out.println(result); // 实际输出:29.969999999999996(而非30.0)​

这是因为DOUBLE是浮点型,无法精确表示所有小数。正确做法:用DECIMAL+BigDecimal:​

-- 数据库字段修改为DECIMAL​

ALTER TABLE `order` MODIFY COLUMN `amount` DECIMAL(10,2) NOT NULL;​

// 实体类修改为BigDecimal​

public class Order {​

private BigDecimal amount; // 对应DECIMAL(10,2)​

}​

// 计算时用BigDecimal的方法​

BigDecimal result = order.getAmount().multiply(new BigDecimal("3"));​

System.out.println(result); // 输出:29.97(精确)​

2.2 字符串型:长度与存储的选择​

MySQL 的字符串类型主要有CHAR、VARCHAR、TEXT三大类,它们的存储方式和适用场景不同,对应的 Java 类型虽以String为主,但映射时需注意长度和存储限制。​

2.2.1 CHAR 与 VARCHAR:固定长度 vs 可变长度​

MySQL 类型​

存储特点​

推荐 Java 类型​

适用场景​

CHAR(M)​

固定长度,M 为 1~255,不足补空格​

String​

长度固定的字符串(如手机号、邮编)​

VARCHAR(M)​

可变长度,M 为 1~65535,按实际长度存储​

String​

长度不固定的字符串(如用户名、地址)​

注意事项:​

  • VARCHAR的实际存储长度受 MySQL 行大小限制(默认行最大 65535 字节),如果字段长度超过这个限制,建议用TEXT。​
  • Java 中String可以接收任意长度的字符串,但需注意 ORM 框架的长度校验(如 JPA 的@Column(length=20)会限制输入长度)。​

实战案例:VARCHAR 长度溢出​

如果 MySQL 字段定义为username VARCHAR(10),Java 实体类用String接收,但插入超过 10 个字符的字符串:​

user.setUsername("abcdefghijk"); // 11个字符​

userMapper.insert(user);​

会抛出截断异常:​

java.sql.SQLException: Data truncation: Data too long for column 'username' at row 1​

解决方法:要么缩短输入字符串,要么修改字段长度(如VARCHAR(20))。​

2.2.2 TEXT 类型:大文本的存储​

当字符串长度超过 65535 字节时,需用TEXT类型。TEXT分TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT,对应不同的存储上限。​

MySQL 类型​

存储上限​

推荐 Java 类型​

适用场景​

TINYTEXT​

255 字节​

String​

短文本(如备注)​

TEXT​

65535 字节​

String​

中等文本(如文章摘要)​

MEDIUMTEXT​

16777215 字节​

String​

长文本(如文章内容)​

LONGTEXT​

4294967295 字节​

String​

超大文本(如日志、备份)​

注意事项:​

  • TEXT类型不能设置默认值,也不适合作为索引(索引效率低)。​
  • MyBatis 中查询TEXT类型时,需确保 ResultMap 正确映射(默认会映射为 String,无需额外配置)。​

2.3 日期时间型:时区与格式的坑​

日期时间类型是最容易出问题的部分,尤其是时区处理。MySQL 的日期时间类型主要有DATE、TIME、DATETIME、TIMESTAMP,对应的 Java 类型需根据场景选择。​

2.3.1 类型对应关系​

MySQL 类型​

存储内容​

时区特性​

推荐 Java 类型(JDK8+)​

不推荐类型(原因)​

DATE​

日期(年 - 月 - 日)​

无时区​

java.time.LocalDate​

java.sql.Date(API 过时)​

TIME​

时间(时:分: 秒)​

无时区​

java.time.LocalTime​

java.sql.Time(API 过时)​

DATETIME​

日期 + 时间(年 - 月 - 日 时:分: 秒)​

无时区(存储原样)​

java.time.LocalDateTime​

java.util.Date(含时区信息,易混淆)​

TIMESTAMP​

日期 + 时间​

受时区影响(存储 UTC 时间)​

java.time.Instant​

java.sql.Timestamp(线程不安全)​

关键区别:​

  • DATETIME存储的是 “字符串形式的日期时间”,插入时是什么值,查询时就是什么值,不随时区变化。​
  • TIMESTAMP存储的是 “UTC 时间戳”,插入时会转换为 UTC 存储,查询时根据当前时区转换为本地时间。​

2.3.2 时区问题实战解析​

假设 MySQL 服务器时区是UTC,应用服务器时区是Asia/Shanghai(UTC+8)。​

场景 1:用DATETIME存储​

插入数据时,应用服务器的时间是2023-10-01 12:00:00(北京时间),直接存入DATETIME字段:​

INSERT INTO log (operate_time) VALUES ('2023-10-01 12:00:00');​

查询时,无论应用服务器时区如何,返回的都是2023-10-01 12:00:00。​

场景 2:用TIMESTAMP存储​

同样插入2023-10-01 12:00:00(北京时间),MySQL 会转换为 UTC 时间2023-10-01 04:00:00存储。​

当应用服务器用Asia/Shanghai时区查询时,会转换为2023-10-01 12:00:00(正确);如果应用服务器时区错误(如UTC),查询结果会是2023-10-01 04:00:00(错误)。​

正确映射方式:​

  • 若用DATETIME,Java 用LocalDateTime接收,无需考虑时区(存储和显示一致)。​
  • 若用TIMESTAMP,Java 用Instant接收(UTC 时间),再转换为本地时间:​

// 实体类​

public class Log {​

private Instant operateTime; // 对应TIMESTAMP​

}​

// 查询后转换为北京时间​

Log log = logMapper.selectById(1);​

LocalDateTime beijingTime = LocalDateTime.ofInstant(​

log.getOperateTime(), ​

ZoneId.of("Asia/Shanghai")​

);​

三、特殊类型对应:枚举、JSON 与二进制​

除了基础类型,MySQL 还有一些特殊类型(如枚举、JSON、二进制),这些类型的映射需要额外处理,尤其是在 ORM 框架中。​

3.1 枚举类型(ENUM)​

MySQL 的ENUM类型用于存储预定义的枚举值,比如性别(男 / 女)、订单状态(待支付 / 已支付 / 已取消)。​

映射规则:​

  • 推荐:Java 用enum类型对应,清晰且类型安全。​
  • 不推荐:用String或Integer(易出错,比如传入未定义的枚举值)。​

实战案例:ENUM 与 Java 枚举的映射​

  1. 定义 MySQL 表:​

CREATE TABLE `user` (​

`id` INT PRIMARY KEY AUTO_INCREMENT,​

`gender` ENUM('MALE', 'FEMALE', 'UNKNOWN') NOT NULL COMMENT '性别'​

);​

  1. 定义 Java 枚举:​

public enum Gender {​

MALE, FEMALE, UNKNOWN​

}​

  1. 实体类映射:​

public class User {​

private Integer id;​

private Gender gender; // 对应ENUM类型​

// getter/setter​

}​

  1. MyBatis 映射(无需额外配置,默认支持枚举名称映射):​

<resultMap id="userMap" type="com.example.User">​

<id column="id" property="id"/>​

<result column="gender" property="gender"/> <!-- 自动映射为Gender枚举 -->​

</resultMap>​

  1. JPA 映射(需用@Enumerated指定映射方式):​

import javax.persistence.Enumerated;​

import javax.persistence.EnumType;​

public class User {​

@Enumerated(EnumType.STRING) // 按枚举名称映射(推荐)​

private Gender gender;​

}​

注意:如果@Enumerated用EnumType.ORDINAL,会按枚举的索引(0,1,2)映射,一旦枚举顺序修改,数据会错乱,因此强烈推荐EnumType.STRING。​

3.2 JSON 类型(MySQL 5.7+)​

MySQL 5.7 及以上支持JSON类型,用于存储 JSON 格式的数据(如用户的扩展信息、商品规格)。Java 中通常有两种映射方式:​

映射方式​

适用场景​

实现方式​

字符串映射​

简单 JSON,无需解析​

用String接收,直接存储 JSON 字符串​

对象映射​

复杂 JSON,需要解析为 Java 对象​

用自定义类 + TypeHandler(MyBatis)或 Converter(JPA)​

实战案例:JSON 与 Java 对象的映射(MyBatis)​

  1. 定义 MySQL 表:​

CREATE TABLE `product` (​

`id` INT PRIMARY KEY AUTO_INCREMENT,​

`spec` JSON NOT NULL COMMENT '商品规格(JSON格式)'​

);​

  1. 定义 JSON 对应的 Java 类:​

public class ProductSpec {​

private String color; // 颜色​

private String size; // 尺寸​

private Integer weight; // 重量(g)​

// getter/setter/toString​

}​

  1. 定义 TypeHandler 处理 JSON 与对象的转换:​

import com.fasterxml.jackson.core.JsonProcessingException;​

import com.fasterxml.jackson.databind.ObjectMapper;​

import org.apache.ibatis.type.BaseTypeHandler;​

import org.apache.ibatis.type.JdbcType;​

import java.sql.CallableStatement;​

import java.sql.PreparedStatement;​

import java.sql.ResultSet;​

import java.sql.SQLException;​

public class JsonTypeHandler<T> extends BaseTypeHandler<T> {​

private static final ObjectMapper mapper = new ObjectMapper();​

private final Class<T> type;​

public JsonTypeHandler(Class<T> type) {​

this.type = type;​

}​

@Override​

public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {​

try {​

ps.setString(i, mapper.writeValueAsString(parameter));​

} catch (JsonProcessingException e) {​

throw new SQLException("Failed to convert object to JSON", e);​

}​

}​

@Override​

public T getNullableResult(ResultSet rs, String columnName) throws SQLException {​

String json = rs.getString(columnName);​

if (json == null) return null;​

try {​

  1. 在 MyBatis 中使用 TypeHandler:​

<resultMap id="productMap" type="com.example.Product">​

<id column="id" property="id"/>​

<result column="spec" property="spec" typeHandler="com.example.JsonTypeHandler"/>​

</resultMap>​

<insert id="insertProduct" parameterType="com.example.Product">​

INSERT INTO product (spec) ​

VALUES (#{spec, typeHandler=com.example.JsonTypeHandler})​

</insert>​

  1. 测试代码:​

Product product = new Product();​

ProductSpec spec = new ProductSpec();​

spec.setColor("RED");​

spec.setSize("L");​

spec.setWeight(500);​

product.setSpec(spec);​

productMapper.insertProduct(product); // 插入成功​

Product saved = productMapper.selectById(1);​

System.out.println(saved.getSpec().getColor()); // 输出:RED​

3.3 二进制类型(BLOB、BIT)​

二进制类型用于存储图片、文件等二进制数据,或位信息(如权限标志)。​

MySQL 类型​

用途​

推荐 Java 类型​

TINYBLOB​

小二进制数据(255 字节)​

byte[]​

BLOB​

二进制数据(65535 字节)​

byte[]​

MEDIUMBLOB​

中二进制数据(16MB)​

byte[]​

LONGBLOB​

大二进制数据(4GB)​

byte[]​

BIT(M)​

位数据(M 为 1~64)​

boolean(M=1 时)、long(M>1 时)​

实战案例:BIT 类型的映射​

MySQL 字段is_vip BIT(1)用于表示是否为 VIP(1 = 是,0 = 否),Java 用boolean接收:​

public class User {​

private Boolean isVip; // 对应BIT(1)​

}​

MyBatis 查询时会自动将BIT(1)转换为boolean(1→true,0→false)。​

如果BIT(3)表示三个权限位(如101表示权限 1 和 3),Java 用long接收:​

public class UserPermission {​

private Long permissions; // 对应BIT(3),存储位数值(如5对应101)​

}​

通过位运算解析权限:​

long permissions = userPermission.getPermissions();​

boolean hasPermission1 = (permissions & 1) != 0; // 第1位​

boolean hasPermission2 = (permissions & 2) != 0; // 第2位(10)​

boolean hasPermission3 = (permissions & 4) != 0; // 第3位(100)​

四、ORM 框架中的类型映射技巧​

日常开发中,我们很少直接用 JDBC 操作数据库,而是通过 ORM 框架(如 MyBatis、JPA)。这些框架对类型映射有默认规则,也支持自定义转换,掌握这些技巧能避免很多坑。​

4.1 MyBatis 的类型映射​

MyBatis 通过TypeHandler处理类型转换,内置了大部分类型的处理器,对于特殊类型需自定义(如 JSON、枚举的特殊映射)。​

4.1.1 全局配置 TypeHandler​

如果某个类型在项目中频繁使用(如 JSON),可在mybatis-config.xml中配置全局 TypeHandler:​

<typeHandlers>​

<typeHandler handler="com.example.JsonTypeHandler" javaType="com.example.ProductSpec"/>​

</typeHandlers>​

配置后,使用时无需每次指定typeHandler。​

4.1.2 枚举的自定义映射​

如果 MySQL 的 ENUM 值与 Java 枚举名称不一致(如 MySQL 是'男',Java 是MALE),可自定义 TypeHandler:​

switch (parameter) {​

case MALE: ps.setString(i, "男"); break;​

case FEMALE: ps.setString(i, "女"); break;​

default: ps.setString(i, "未知");​

}​

}​

@Override​

public Gender getNullableResult(ResultSet rs, String columnName) throws SQLException {​

// MySQL字符串→Java枚举​

String gender = rs.getString(columnName);​

switch (gender) {​

case "男": return Gender.MALE;​

case "女": return Gender.FEMALE;​

default: return Gender.UNKNOWN;​

}​

}​

// 其他方法省略​

}​

4.2 JPA 的类型映射​

JPA(如 Hibernate)有更强大的自动映射能力,通过注解可轻松实现复杂类型转换。​

4.2.1 日期时间的时区配置​

JPA 默认会根据 JVM 时区转换日期,若需指定时区,可在application.properties中配置:​

# Spring Data JPA配置​

spring.jpa.properties.hibernate.jdbc.time_zone=Asia/Shanghai​

4.2.2 自定义属性转换器(Converter)​

对于 JSON 类型,JPA 可通过@Converter自定义转换:​

import javax.persistence.Converter;​

import javax.persistence.AttributeConverter;​

import com.fasterxml.jackson.databind.ObjectMapper;​

@Converter(autoApply = true) // 自动应用到所有ProductSpec类型​

public class ProductSpecConverter implements AttributeConverter<ProductSpec, String> {​

private static final ObjectMapper mapper = new ObjectMapper();​

@Override​

public String convertToDatabaseColumn(ProductSpec attribute) {​

try {​

return mapper.writeValueAsString(attribute);​

} catch (Exception e) {​

throw new IllegalArgumentException("Failed to convert to JSON", e);​

}​

}​

@Override​

public ProductSpec convertToEntityAttribute(String dbData) {​

try {​

return mapper.readValue(dbData, ProductSpec.class);​

} catch (Exception e) {​

throw new IllegalArgumentException("Failed to convert from JSON", e);​

}​

}​

}​

实体类中直接使用:​

import javax.persistence.Entity;​

import javax.persistence.Id;​

@Entity​

public class Product {​

@Id​

private Integer id;​

private ProductSpec spec; // 自动使用ProductSpecConverter转换​

// getter/setter​

}​

五、常见问题与避坑指南​

即使掌握了基础映射规则,实际开发中仍可能遇到各种问题。这里总结了 5 个高频问题及解决方案。​

5.1 问题 1:整数类型溢出​

现象:查询或插入时抛出Out of range异常。​

原因:Java 类型的范围小于 MySQL 字段类型的范围(如用int接收BIGINT)。​

解决方案:​

  • 参考 2.1.1 的类型对应表,确保 Java 类型范围覆盖 MySQL 类型。​
  • 无符号类型(UNSIGNED)需用更大的 Java 类型(如INT UNSIGNED→long)。​

5.2 问题 2:日期时间差 8 小时​

现象:查询的日期时间比数据库中存储的少 8 小时。​

原因:​

  • MySQL 时区与应用服务器时区不一致(如 MySQL 是 UTC,应用是北京时间)。​
  • TIMESTAMP类型会随时区转换,而DATETIME不会。​

解决方案:​

  • 统一 MySQL 和应用服务器的时区(推荐设为 UTC 或 Asia/Shanghai)。​
  • 用LocalDateTime接收DATETIME,用Instant接收TIMESTAMP并显式指定时区转换。​

5.3 问题 3:Decimal 精度丢失​

现象:数值计算结果与预期不符(如 9.99*3=29.969999...)。​

原因:用double接收DECIMAL类型,浮点运算导致精度丢失。​

解决方案:​

  • 强制用BigDecimal接收DECIMAL类型。​
  • 计算时使用BigDecimal的add、multiply等方法,避免转换为double。​

5.4 问题 4:字符串截断​

现象:插入时抛出Data truncation异常。​

原因:输入字符串长度超过 MySQL 字段定义的长度(如VARCHAR(10)插入 11 个字符)。​

解决方案:​

  • 前端限制输入长度,与数据库字段长度保持一致。​
  • 后端用@Size(JPA)或自定义校验注解校验长度。​
  • 必要时修改数据库字段长度(如VARCHAR(20))。​

5.5 问题 5:枚举值不匹配​

现象:插入时抛出Data truncation: Incorrect enum value异常。​

原因:Java 枚举值不在 MySQLENUM定义的范围内。​

解决方案:​

  • 确保 Java 枚举与 MySQLENUM的取值完全一致。​
  • 新增枚举值时,先修改数据库ENUM定义,再更新 Java 枚举。​

六、实战案例:完整用户表的类型映射​

为了让你更直观地理解类型映射,我们设计一个完整的用户表,包含多种类型的字段,并实现 Java 实体类与 ORM 映射。​

6.1 数据库表设计​

CREATE TABLE `user` (​

`id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID',​

`username` VARCHAR(50) NOT NULL COMMENT '用户名',​

`age` TINYINT UNSIGNED NOT NULL COMMENT '年龄(0-255)',​

`height` DECIMAL(5,2) COMMENT '身高(米,如1.75)',​

`register_time` DATETIME NOT NULL COMMENT '注册时间',​

`last_login_time` TIMESTAMP NULL COMMENT '最后登录时间',​

`gender` ENUM('MALE', 'FEMALE', 'UNKNOWN') NOT NULL COMMENT '性别',​

`preferences` JSON COMMENT '偏好设置(JSON格式)',​

`is_vip` BIT(1) NOT NULL DEFAULT b'0' COMMENT '是否VIP',​

`avatar` MEDIUMBLOB COMMENT '头像(二进制)'​

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;​

6.2 Java 实体类​

import org.hibernate.annotations.Type;​

public class User {​

private Long id; // BIGINT→Long​

private String username; // VARCHAR(50)→String​

private Short age; // TINYINT UNSIGNED→Short​

private BigDecimal height; // DECIMAL(5,2)→BigDecimal​

private LocalDateTime registerTime; // DATETIME→LocalDateTime​

private Instant lastLoginTime; // TIMESTAMP→Instant​

private Gender gender; // ENUM→Gender枚举​

private Map<String, Object> preferences; // JSON→Map(或自定义类)​

private Boolean isVip; // BIT(1)→Boolean​

private byte[] avatar; // MEDIUMBLOB→byte[]​

// getter/setter​

}​

// 性别枚举​

public enum Gender {​

MALE, FEMALE, UNKNOWN​

}​

6.3 MyBatis 映射文件​

<mapper namespace="com.example.UserMapper">​

<resultMap id="userMap" type="com.example.User">​

<id column="id" property="id"/>​

<result column="username" property="username"/>​

<result column="age" property="age"/>​

<result column="height" property="height"/>​

<result column="register_time" property="registerTime"/>​

<result column="last_login_time" property="lastLoginTime"/>​

<result column="gender" property="gender"/>​

<result column="preferences" property="preferences" typeHandler="com.example.JsonTypeHandler"/>​

<result column="is_vip" property="isVip"/>​

<result column="avatar" property="avatar"/>​

</resultMap>​

<insert id="insertUser" parameterType="com.example.User">​

INSERT INTO `user` (​

username, age, height, register_time, last_login_time,​

gender, preferences, is_vip, avatar​

6.4 测试代码​


public void t

@Test​

estUserMapping() {​

// 创建用户​

User user = new User();​

user.setUsername("张三");​

user.setAge((short) 28);​

user.setHeight(new BigDecimal("1.75"));​

user.setRegisterTime(LocalDateTime.now());​

user.setLastLoginTime(Instant.now());​

user.setGender(Gender.MALE);​

Map<String, Object> preferences = new HashMap<>();​

preferences.put("language", "zh-CN");​

preferences.put("theme", "dark");​

user.setPreferences(preferences);​

user.setIsVip(true);​

user.setAvatar(new byte[]{0x89, 0x50, 0x4E, 0x47}); // 示例图片二进制数据​

七、总结​

MySQL 字段类型与 Java 字段类型的对应,看似是基础知识点,实则贯穿整个开发流程,影响着系统的稳定性和数据的准确性。本文从基础类型到特殊类型,从手动映射到 ORM 框架自动映射,全方位解析了类型对应的规则和技巧,并通过实战案例拆解了常见问题。​

核心要点总结:​

  1. 数值类型:根据范围选择 Java 类型,DECIMAL必须用BigDecimal。​
  1. 字符串类型:VARCHAR和TEXT都用String,注意长度限制。​
  1. 日期时间:DATETIME→LocalDateTime,TIMESTAMP→Instant,重视时区问题。​
  1. 特殊类型:ENUM用 Java 枚举,JSON用自定义对象 + 转换器,二进制用byte[]。​
  1. ORM 框架:MyBatis 用TypeHandler,JPA 用@Converter,简化复杂类型映射。​

掌握这些知识,你就能轻松避开类型映射的各种 “坑”,写出更健壮的代码。如果觉得本文对你有帮助,欢迎点赞收藏,也欢迎在评论区分享你的类型映射经验!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值