MySQL TINYINT(1) 被 MyBatis-Plus 映射成 Boolean 的坑

3 阅读2分钟

背景

用 MyBatis-Plus 的代码生成器生成实体时,遇到一个奇怪的问题:

数据库里 article.status 字段是 TINYINT(1),生成的 Java 实体里却是 Boolean 类型。

但我的业务代码是用 Integer 写的——0 草稿 / 1 发布,编译直接报错:

不兼容的类型: int 无法转换为 java.lang.Boolean

现象

数据库里字段:

`status` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '状态:0草稿 1已发布'

生成的 Java 实体:

@TableField("status")
private Boolean status;   // ← 变成了 Boolean

我的代码:

article.setStatus(1);   // ❌ 编译不过

原因

MySQL 的 TINYINT(1) 会被 JDBC 驱动识别为"布尔类型"。

  • TINYINT(1) → 被识别为 BOOLEAN(因为 (1) 表示"只存 1 位");
  • TINYINT(不带 (1))→ 被识别为 Byte;
  • INT → 被识别为 Integer。

MyBatis-Plus 生成器是按 JDBC 驱动返回的类型来映射 Java 类型的,所以:

MySQL 类型Java 映射
TINYINT(1)Boolean
TINYINTByte
INT / INTEGERInteger
BIGINTLong

这就是为什么 status 变成了 Boolean。

解决

把业务状态字段的类型改成 INT:

ALTER TABLE article MODIFY COLUMN `status` INT NOT NULL DEFAULT 0 COMMENT '状态:0草稿 1已发布';

然后重新生成实体:

  1. 删掉旧的 Article.java;
  2. 跑生成器;
  3. 新生成的实体里 status 就是 Integer。

编译通过。

但 deleted 字段为什么要保留 TINYINT(1)?

逻辑删除字段 deleted 用 TINYINT(1) → Boolean,这是对的——因为逻辑删除就是"删了 / 没删"两态语义,Boolean 完全合适:

@TableLogic
private Boolean deleted;

改成 INT 反而要写 @TableLogic(value = "1", delval = "0"),更麻烦。

总结

建表规范:

字段类型用什么 MySQL 类型
业务状态(0/1/2...)INT
数量(浏览量、库存等)INT 或 BIGINT
逻辑删除TINYINT(1)
布尔标志TINYINT(1)

一句话:别用 TINYINT(1) 存状态码,用 INT。

参考

本文是"踩坑系列"第 2 篇,第 1 篇:Element Plus el-dialog 在 sticky header 里弹不出的坑