认真冷静专注集中. 2025-05-30 17:19 采纳率: 0%
浏览 58

MybatisPlus往Mysql中写入数据,id自增数很大

本人在写苍穹外卖时,因为不想在xml里配置sql语句,又想到苍穹外卖难度较低所以决定使用mybatis-plus来对mysql进行读写操作。

我在我的entity实体类中均加入了@TableName@TableId(type = IdType.AUTO),并且也在配置文件中配置了

mybatis-plus:
   global-config:
      db-config:
        id-type: auto

并且数据库表中所有的id主键都在建表时都加入了AUTO_INCREMENT
可是在执行如新增员工:

@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);
    }

或新增菜品类别时:

@Override
    public void save(CategoryDTO categoryDTO) {
        Category category = BeanUtil.copyProperties(categoryDTO, Category.class);
        category.setStatus(StatusConstant.DISABLE);
        category.setCreateTime(LocalDateTime.now());
        category.setUpdateTime(LocalDateTime.now());
        category.setCreateUser(BaseContext.getCurrentId());
        category.setUpdateUser(BaseContext.getCurrentId());

        categoryMapper.insert(category);
    }

最后存入数据库的id值都是这样的数字1928344360402522127。
想知道一下,这是什么情况?以前从来没有遇到过
而且这似乎还导致了前端js精度丢失的问题,导致了该数据需要使用id的功能都会因为id精度丢失而无法执行成功

  • 写回答

5条回答 默认 最新

  • 檀越@新空间 2025-05-30 17:20
    关注

    下午好🌅🌅🌅
    本答案参考通义千问

    分析问题

    从你的描述来看,MyBatis-Plus 和 MySQL 数据库的 id 自增字段生成的值异常大(例如 1928344360402522127),这种现象通常与以下几种情况相关:

    1. MySQL 的 BIGINT 类型

      • MySQL 中的 BIGINT 是 64 位有符号整数类型,其取值范围为 -92233720368547758089223372036854775807
      • 如果你使用的是 BIGINT UNSIGNED,那么它的取值范围是 018446744073709551615
      • 如果你的 id 字段定义为 BIGINTBIGINT UNSIGNED,MySQL 的自增机制可能会生成非常大的值。
    2. MyBatis-Plus 的 IdType.AUTO 配置

      • 在 MyBatis-Plus 中,IdType.AUTO 表示让数据库自行管理主键生成逻辑(通常是通过 AUTO_INCREMENT 实现)。
      • 如果数据库的自增字段没有正确配置或被手动插入了较大的值,后续插入的数据会继续从这个较大的值开始递增。
    3. 前端精度丢失问题

      • JavaScript 的 Number 类型是基于 IEEE 754 标准的双精度浮点数,其最大安全整数值为 2^53 - 1(即 9007199254740991)。如果传递给前端的 id 值超过了这个范围,会导致精度丢失。

    解决方案

    以下是解决该问题的具体步骤和代码调整建议:

    1. 确认数据库表的 id 字段类型

    检查数据库表的 id 字段是否定义为 BIGINTBIGINT UNSIGNED。如果是,可以尝试将其改为 INTBIGINT 的有符号类型(BIGINTINT 的范围通常足够应对大多数业务场景)。

    修改表结构的 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 自增字段生成过大值的问题,并避免前端精度丢失的风险。具体选择哪种方式取决于你的业务需求和技术栈:

    1. 如果业务场景允许,优先推荐使用雪花算法生成全局唯一 ID。
    2. 如果必须使用数据库自增机制,可以将字段类型改为 INTBIGINT,并确保表结构正确配置。

    希望这些解决方案能帮助你解决问题!

    评论

报告相同问题?

问题事件

  • 创建了问题 5月30日