使用Mybatis-plus出现数据库id很大或者为负数情况排查解决

背景介绍

在使用 MyBatis-Plus 框架时,主键生成是一个常见的需求。MyBatis-Plus 提供了多种主键生成策略,其中包括数据库自增、UUID 和雪花算法。雪花算法因其在高并发场景下的高效性和唯一性而被广泛采用。然而,有时候开发者会遇到使用雪花算法生成的主键值异常大,甚至为负数的问题。

问题描述

在使用 MyBatis-Plus 时,如果主键生成策略设置为雪花算法,可能会遇到以下问题:

  • 新增记录时,生成的主键值异常大。
  • 有时候生成的主键值为负数。

这些问题会导致数据库主键冲突,影响系统的稳定性和数据的一致性。

原因分析

1. 代码未设置 @TableId 注解

在实体类中,如果主键字段没有正确设置 @TableId 注解,MyBatis-Plus 将无法正确识别主键生成策略,从而导致生成的主键值异常。

2. 字段类型设置不当

如果主键字段的类型设置为 Integer 或数据库字段类型设置为 INT,而主键生成策略设置为雪花算法,可能会导致生成的主键值超出 Integer 或 INT 的范围,从而生成负数。

3. 雪花算法参数配置不当

雪花算法生成的主键值由时间戳、机器标识和序列号组成。如果时间戳部分过大,或者机器标识和序列号部分配置不当,都会导致生成的主键值异常大。

4. 数据库表初始值设置不当

即使代码中正确设置了 @TableId 注解,如果数据库表的初始值设置不当,也会导致生成的主键值异常。例如,如果数据库表的 AUTO_INCREMENT 初始值设置得过大,后续插入的数据也会受到影响。

解决方案

1. 设置 @TableId 注解

确保在实体类中正确设置 @TableId 注解,并指定主键生成策略为雪花算法。例如:

java 复制代码
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;

public class User {
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private Long id;

    private String name;
    private String email;

    // getters and setters
}

2. 调整字段类型

确保主键字段的类型设置为 Long,并且数据库字段类型设置为 BIGINT,以避免生成的主键值超出范围。例如:

java 复制代码
public class User {
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private Long id;

    private String name;
    private String email;

    // getters and setters
}

数据库字段类型设置为 BIGINT:

sql 复制代码
CREATE TABLE users (
    id BIGINT NOT NULL AUTO_INCREMENT,
    name VARCHAR(255),
    email VARCHAR(255),
    PRIMARY KEY (id)
);

3. 检查雪花算法参数配置

确保雪花算法的参数配置合理。MyBatis-Plus 默认的雪花算法配置通常是合理的,但如果需要自定义参数,可以参考以下配置:

yaml 复制代码
  global-config:
    dbConfig:
      # 主键类型
      # AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID
      idType: ASSIGN_ID

4. 调整数据库表初始值

如果数据库表的 AUTO_INCREMENT 初始值设置得过大,可以通过以下 SQL 语句将其调整为合理的值:

sql 复制代码
ALTER TABLE users AUTO_INCREMENT = 1;

5. 重启后台服务

在调整完代码和数据库配置后,重启后台服务以确保所有更改生效。

示例代码

实体类

java 复制代码
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;

public class User {
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private Long id;

    private String name;
    private String email;

    // getters and setters
}

映射文件

xml 复制代码
<mapper namespace="com.example.mapper.UserMapper">
    <insert id="insertUser">
        INSERT INTO users (name, email)
        VALUES (#{name}, #{email})
    </insert>
</mapper>

数据库配置

yaml 复制代码
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydatabase
    username: root
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver

  global-config:
    dbConfig:
      # 主键类型
      # AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID
      idType: ASSIGN_ID

结论

通过正确设置 @TableId 注解、调整字段类型、检查雪花算法参数配置、调整数据库表初始值,并重启后台服务,可以有效解决使用 MyBatis-Plus 时生成的主键值异常大或为负数的问题。

相关推荐
AIgorithmGEEK6 小时前
MySQL 索引全解(下):建、查、删实战与知识速查表
数据库·mysql·b+树·索引
唠点键盘之外的8 小时前
26 向量数据库实战:从 0 搭一条能用的检索链路(pgvector + Spring AI)
数据库·人工智能·spring
云和恩墨8 小时前
数据库监控简史:监控不止于告警——从图表大爆发到健康管理闭环
数据库
ly76898 小时前
MongoDB 事务开销实测:快照隔离下的写冲突、重试与分片事务边界
数据库·mongodb·事务·分片集群·快照隔离·写冲突
豆角焖肉9 小时前
Spring AOP 自定义注解实现系统操作日志
数据库·自定义注解·springaop·操作日志·aop 切面
金伟API102410 小时前
不会写复杂SQL怎么办?
数据库·sql
执笔为剑10 小时前
2.1.2-1、V8R3迁移到V8R6-Oracle兼容特性
数据库
江湖有缘10 小时前
Docker实战 | 使用Docker部署rmoments社交平台
jvm·docker·oracle
geovindu10 小时前
sql:Search-Optimized SQL Queries using mysql 9.0
android·数据库·sql·mysql·数据库开发·数据库架构
for_ever_love__11 小时前
MySQL SELECT 与 WHERE 优化实战:可搜索条件、联合索引与执行计划
数据库·mysql·oracle·select·where·条件优化·查询优化技巧