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

背景介绍

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

问题描述

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

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

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

原因分析

1. 代码未设置 @TableId 注解

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

2. 字段类型设置不当

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

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

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

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

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

解决方案

1. 设置 @TableId 注解

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

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,以避免生成的主键值超出范围。例如:

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

    private String name;
    private String email;

    // getters and setters
}

数据库字段类型设置为 BIGINT

CREATE TABLE users (
    id BIGINT NOT NULL AUTO_INCREMENT,
    name VARCHAR(255),
    email VARCHAR(255),
    PRIMARY KEY (id)
);

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

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

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

4. 调整数据库表初始值

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

ALTER TABLE users AUTO_INCREMENT = 1;

5. 重启后台服务

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

示例代码

实体类

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
}

映射文件

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

数据库配置

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 时生成的主键值异常大或为负数的问题。

- 域名信息:192.168.1.38 分页参数: pageNum=1, pageSize=10 查询条件: ChatAgentRecordBo(id=null, userId=null, content=null, sessionId=null, role=null, deductCost=null, totalTokens=null, modelName=null, remark=null, deductPower=0.0, agentName=null, tenantId=null, userName=null) 分页查询结果:[] 数据类型:class java.util.Collections$EmptyList 分页查询结果总数量: 8 分页查询结果数据: [] [ChatAgentRecordVo(id=1954722490187579394, userId=1954144358602702850, sessionId=7082b27c-4ec6-4b46-ba5c-e34924e7c7d1, content=你好,我是一个专业的舆情监控智能体,能够全面且精准地在全网(涵盖社交平台、视频网站、新闻门户网站、电商平台等各类网络平台)抓取企业、品牌、产品信息,并生成综合报告,您想要监控的的企业名称或产品是什么? 请输入完成的企业名称以及产品 示例企业: 聚味瞿记、雅绣集湘绣、艾瑞力机械 示例问题:, role=assistant, deductCost=0.0, totalTokens=0, modelName=null, remark=null, createTime=Mon Aug 11 09:52:13 CST 2025, deductPower=0.0, agentName=企业舆情, tenantId=00000, userName=17775825382), ChatAgentRecordVo(id=1954722388521844738, userId=1954144358602702850, sessionId=7082b27c-4ec6-4b46-ba5c-e34924e7c7d1, content=你好,我是一个专业的舆情监控智能体,能够全面且精准地在全网(涵盖社交平台、视频网站、新闻门户网站、电商平台等各类网络平台)抓取企业、品牌、产品信息,并生成综合报告,您想要监控的的企业名称或产品是什么? 请输入完成的企业名称以及产品 示例企业: 聚味瞿记、雅绣集湘绣、艾瑞力机械 示例问题:, role=user, deductCost=0.0, totalTokens=0, modelName=null, remark=null, createTime=Mon Aug 11 09:51:49 CST 2025, deductPower=0.0, agentName=企业舆情, tenantId=00000, userName=17775825382), ChatAgentRecordVo(id=1954144625335271425, userId=1954144358602702850, sessionId=fa8312f1-faf4-4d0f-8286-87e63165eaee, content=你好,我是智谱极速推理版,国内最快推理模型,推理速度最快可达 200 tokens/秒,比常规推理模型快 8 倍,快,更快,最快!来体验一下飞一般的感觉吧! 示例问题:, role=assistant, deductCost=0.0, totalTokens=0, modelName=null, remark=null, createTime=Sat Aug 09 19:36:00 CST 2025, deductPower=0.0, agentName=智谱极速推理版, tenantId=00000, userName=17775825382), ChatAgentRecordVo(id=1954144456527118337, userId=1954144358602702850, sessionId=fa8312f1-faf4-4d0f-8286-87e63165eaee, content=你好,我是智谱极速推理版,国内最快推理模型,推理速度最快可达 200 tokens/秒,比常规推理模型快 8 倍,快,更快,最快!来体验一下飞一般的感觉吧! 示例问题:, role=user, deductCost=0.0, totalTokens=0, modelName=null, remark=null, createTime=Sat Aug 09 19:35:19 CST 2025, deductPower=0.0, agentName=智谱极速推理版, tenantId=00000, userName=17775825382), ChatAgentRecordVo(id=1953738347945459713, userId=1942137741196181506, sessionId=46cedd1e-0ad2-4b7e-a279-67c3eab5bcba, content=你好,我是采购总监,我能助力采购决策。分析市场动态、供应商数据,优化采购流程,降低成本,提升效率与质量。 示例问题:, role=assistant, deductCost=0.0, totalTokens=0, modelName=null, remark=null, createTime=Fri Aug 08 16:41:36 CST 2025, deductPower=0.0, agentName=采购总监Agent, tenantId=00000, userName=17775825283), ChatAgentRecordVo(id=1953737995766530050, userId=1942137741196181506, sessionId=46cedd1e-0ad2-4b7e-a279-67c3eab5bcba, content=你好,我是采购总监,我能助力采购决策。分析市场动态、供应商数据,优化采购流程,降低成本,提升效率与质量。 示例问题:, role=user, deductCost=0.0, totalTokens=0, modelName=null, remark=null, createTime=Fri Aug 08 16:40:12 CST 2025, deductPower=0.0, agentName=采购总监Agent, tenantId=00000, userName=17775825283), ChatAgentRecordVo(id=1953735316457717761, userId=1942137741196181506, sessionId=null, content=你好,我是采购总监,我能助力采购决策。分析市场动态、供应商数据,优化采购流程,降低成本,提升效率与质量。 示例问题:, role=assistant, deductCost=0.0, totalTokens=0, modelName=null, remark=null, createTime=Fri Aug 08 16:29:33 CST 2025, deductPower=0.0, agentName=采购总监Agent, tenantId=00000, userName=17775825283), ChatAgentRecordVo(id=1953734945853210625, userId=1942137741196181506, sessionId=null, content=你好,我是采购总监,我能助力采购决策。分析市场动态、供应商数据,优化采购流程,降低成本,提升效率与质量。 示例问题:, role=user, deductCost=0.0, totalTokens=0, modelName=null, remark=null, createTime=Fri Aug 08 16:28:04 CST 2025, deductPower=0.0, agentName=采购总监Agent, tenantId=00000, userName=17775825283)] @Override public TableDataInfo<ChatAgentRecordVo> queryPageList(ChatAgentRecordBo bo, PageQuery pageQuery) { // 处理分页参数为空的情况 int pageNum = (pageQuery.getPageNum() == null) ? 1 : pageQuery.getPageNum(); int pageSize = (pageQuery.getPageSize() == null) ? 10 : pageQuery.getPageSize(); Page<ChatAgentRecordVo> page = new Page<>(pageNum,pageSize); System.out.println("分页参数: pageNum=" + pageNum + ", pageSize=" + pageSize); System.out.println("查询条件: " + bo); baseMapper.selectAgentRecordList(page, bo); System.out.println("分页查询结果:" + page.getRecords()); System.out.println("数据类型:" + page.getRecords().getClass()); // 应输出class java.util.ArrayList if (!page.getRecords().isEmpty()) { System.out.println("元素类型:" + page.getRecords().getClass()); //应输出class org.ruoyi.domain.ChatAgentRecordVo } // 打印分页结果 System.out.println("分页查询结果总数量: " + page.getTotal()); System.out.println("分页查询结果数据: " + page.getRecords()); System.out.println(baseMapper.selectAgentRecordList(page, bo)); return TableDataInfo.build(page); }<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="org.ruoyi.mapper.ChatAgentRecordMapper"> <sql id="baseJoinSql"> SELECT car.id, car.session_id, car.user_id, su.user_name AS userName, car.content, car.role, car.agent_name, car.deduct_cost, car.total_tokens, car.create_time, car.tenant_id FROM chat_agent_record car LEFT JOIN sys_user su ON car.user_id = su.user_id and car.tenant_id=su.tenant_id </sql> <select id="selectAgentRecordList" parameterType="org.ruoyi.domain.bo.ChatAgentRecordBo" resultType="org.ruoyi.domain.vo.ChatAgentRecordVo"> SELECT car.id, car.session_id, car.user_id, su.user_name AS userName, car.content, car.role, car.agent_name, car.deduct_cost, car.total_tokens, car.create_time, car.tenant_id FROM chat_agent_record car LEFT JOIN sys_user su ON car.user_id = su.user_id and car.tenant_id=su.tenant_id ORDER BY car.create_time DESC <!-- -- <include refid="baseJoinSql"/>--> <!-- <where>--> <!-- car.tenant_id = #{bo.tenantId}--> <!-- <if test="bo.userId != null">--> <!-- AND car.user_id = #{bo.userId}--> <!-- </if>--> <!-- <if test="bo.agentName != null and bo.agentName != ''">--> <!-- AND car.agent_name LIKE CONCAT('%', #{bo.agentName}, '%')--> <!-- </if>--> <!-- <if test="bo.userName != null and bo.userName != ''">--> <!-- AND su.user_name LIKE CONCAT('%', #{bo.userName}, '%')--> <!-- </if>--> <!-- <if test="bo.params != null and bo.params.beginTime != null and bo.params.endTime != null">--> <!-- AND car.create_time BETWEEN #{bo.params.beginTime} AND #{bo.params.endTime}--> <!-- </if>--> <!-- </where>--> </select> </mapper> 为什么还是查询为{ "total": 8, "rows": [], "code": 200, "msg": "查询成功" }
08-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值