下午好🌅🌅🌅
本答案参考通义千问
分析问题
从你的描述来看,MyBatis-Plus 和 MySQL 数据库的 id 自增字段生成的值异常大(例如 1928344360402522127),这种现象通常与以下几种情况相关:
-
MySQL 的 BIGINT 类型:
- MySQL 中的
BIGINT 是 64 位有符号整数类型,其取值范围为 -9223372036854775808 到 9223372036854775807。 - 如果你使用的是
BIGINT UNSIGNED,那么它的取值范围是 0 到 18446744073709551615。 - 如果你的
id 字段定义为 BIGINT 或 BIGINT UNSIGNED,MySQL 的自增机制可能会生成非常大的值。
-
MyBatis-Plus 的 IdType.AUTO 配置:
- 在 MyBatis-Plus 中,
IdType.AUTO 表示让数据库自行管理主键生成逻辑(通常是通过 AUTO_INCREMENT 实现)。 - 如果数据库的自增字段没有正确配置或被手动插入了较大的值,后续插入的数据会继续从这个较大的值开始递增。
-
前端精度丢失问题:
- JavaScript 的
Number 类型是基于 IEEE 754 标准的双精度浮点数,其最大安全整数值为 2^53 - 1(即 9007199254740991)。如果传递给前端的 id 值超过了这个范围,会导致精度丢失。
解决方案
以下是解决该问题的具体步骤和代码调整建议:
1. 确认数据库表的 id 字段类型
检查数据库表的 id 字段是否定义为 BIGINT 或 BIGINT UNSIGNED。如果是,可以尝试将其改为 INT 或 BIGINT 的有符号类型(BIGINT 或 INT 的范围通常足够应对大多数业务场景)。
修改表结构的 SQL 示例:
ALTER TABLE your_table_name MODIFY COLUMN id INT AUTO_INCREMENT;
2. 修改 MyBatis-Plus 的 id-type 配置
如果你希望 MyBatis-Plus 自动管理主键生成逻辑,可以将 id-type 设置为 auto。确保配置文件中的设置如下:
mybatis-plus:
global-config:
db-config:
id-type: auto
3. 手动控制主键生成策略
如果希望避免 MySQL 的自增机制带来的问题,可以改为使用全局唯一 ID 生成器(如雪花算法)或其他 UUID 方式。
修改实体类的注解:
将 @TableId(type = IdType.AUTO) 替换为 @TableId(type = IdType.INPUT) 或其他适合的生成策略。
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
public class Employee {
@TableId(type = IdType.ASSIGN_ID) // 使用全局唯一 ID 生成器
private Long id;
// 其他字段...
}
配置全局唯一 ID 生成器:
在 MyBatis-Plus 配置类中启用雪花算法:
@Configuration
public class MyBatisPlusConfig {
@Bean
public DefaultGlobalConfiguration globalConfiguration() {
DefaultGlobalConfiguration globalConfig = new DefaultGlobalConfiguration();
globalConfig.setIdType(IdType.ASSIGN_ID); // 使用雪花算法生成全局唯一 ID
return globalConfig;
}
}
4. 前端处理精度丢失问题
如果前端必须使用较大范围的 id 值,可以考虑以下两种方式:
-
使用字符串存储 id:
将 id 字段定义为 VARCHAR 类型,并在数据库中存储为字符串格式。这样可以避免精度丢失问题。
-
前端使用 BigInt:
在 JavaScript 中使用 BigInt 类型来处理超大整数。例如:
const id = BigInt("1928344360402522127");
console.log(id.toString()); // 输出原始值
修改后的代码示例
假设我们选择使用雪花算法生成全局唯一 ID,以下是修改后的代码示例:
实体类
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
public class Employee {
@TableId(type = IdType.ASSIGN_ID) // 使用雪花算法生成全局唯一 ID
private Long id;
private String name;
private String password;
private Status status;
private LocalDateTime createTime;
private LocalDateTime updateTime;
private Long createUser;
private Long updateUser;
// Getter 和 Setter 方法
}
Mapper 接口
无需额外修改,MyBatis-Plus 会自动处理主键生成逻辑。
Service 层
@Override
public void save(EmployeeDTO employee) {
Employee employeeEntity = BeanUtil.copyProperties(employee, Employee.class);
employeeEntity.setStatus(StatusConstant.ENABLE);
employeeEntity.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
employeeEntity.setCreateTime(LocalDateTime.now());
employeeEntity.setUpdateTime(LocalDateTime.now());
employeeEntity.setCreateUser(BaseContext.getCurrentId());
employeeEntity.setUpdateUser(BaseContext.getCurrentId());
employeeMapper.insert(employeeEntity);
}
配置类
@Configuration
public class MyBatisPlusConfig {
@Bean
public DefaultGlobalConfiguration globalConfiguration() {
DefaultGlobalConfiguration globalConfig = new DefaultGlobalConfiguration();
globalConfig.setIdType(IdType.ASSIGN_ID); // 使用雪花算法生成全局唯一 ID
return globalConfig;
}
}
总结
通过以上步骤,你可以有效解决 MySQL 自增字段生成过大值的问题,并避免前端精度丢失的风险。具体选择哪种方式取决于你的业务需求和技术栈:
- 如果业务场景允许,优先推荐使用雪花算法生成全局唯一 ID。
- 如果必须使用数据库自增机制,可以将字段类型改为
INT 或 BIGINT,并确保表结构正确配置。
希望这些解决方案能帮助你解决问题!