insert插入新增记录后如何获取自增的主键id?

需求:由于主键是自增的int型,insert操作时服务端并未对其赋值,导致在insert时封装的对象其主键是null的,可是我们需要获取到主键

 

使用环境:逆向的mybatis

 

实现方式:修改mapper对象的insert方法,如下:

        <insert id="insert" useGeneratedKeys="true" keyProperty="examId" parameterType="entity.table.Exam" >
        .........
        </insert>

只需要新增useGeneratedKeyskeyProperty即可,keyProperty的值为实体的字段。作用是把自增的主键的值赋给实例化的对象。

 

<think>我们正在使用MyBatisPlus的`saveOrUpdateBatch`方法,并希望获取主键ID。根据引用[1],MyBatisPlus的批量操作方法在默认情况下可能存在性能问题,但我们的焦点是获取ID。在MyBatisPlus中,当我们执行插入操作时,如果数据库表的主键是自的,并且我们在实体类的主键字段上正确配置了主键策略,那么插入成功后,自主键会自动回填到实体对象的主键属性中。但是,`saveOrUpdateBatch`方法同时包含保存(插入)和更新两种情况。对于插入操作主键是自的,我们需要回填主键ID;对于更新操作主键已经存在,不需要回填。关键点:1.确保实体类的主键字段使用正确的注解(`@TableId`)配置主键策略。对于自主键,通常使用`IdType.AUTO`(引用[2])。2.`saveOrUpdateBatch`方法执行后,被插入的实体对象的主键字段会被自动填充(更新操作不会改变主键字段,因为主键已经存在)。步骤:1.检查实体类的主键字段配置:```javapublicclassSysUser{@TableId(value="id",type=IdType.AUTO)//使用数据库自主键privateLongid;//其他字段...}```这样配置后,当执行插入操作时,MyBatisPlus会通过JDBC的`getGeneratedKeys`方法获取主键并回填到实体对象的`id`属性。2.调用`saveOrUpdateBatch`方法后,传入的实体列表中被插入(而不是更新)的实体对象的主键字段会被自动赋。示例:```javaList<SysUser>userList=...;//待保存或更新的用户列表//假设其中部分用户是新的(id为null或0),部分已有(id)booleanresult=userService.saveOrUpdateBatch(userList);//执行后,新的用户对象的id会被设置为数据库生成的自IDfor(SysUseruser:userList){if(user.getId()!=null){System.out.println("用户ID:"+user.getId());}}```注意:-对于更新操作,实体对象的主键字段在调用方法之前就应该有(即非空),因此更新后主键字段不会改变。-对于插入操作,实体对象的主键字段在执行前应为null(或0,取决于类型),执行后会被赋为数据库生成的自ID。潜在问题:-引用[3]中提到,如果主键冲突(例如重复主键)会抛出异常,因此需要确保主键策略正确,避免手动设置自主键。-引用[1]指出默认的批量操作性能可能不佳,如果数据量很大,建议使用自定义的批量处理方法(如分批次处理)或优化数据库配置。结论:使用`saveOrUpdateBatch`方法后,插入的实体对象会自动获取主键ID,我们只需检查实体列表中的对象主键字段即可。优化建议(针对性能):如果数据量很大,可以考虑将列表分批次调用`saveOrUpdateBatch`,例如每1000条执行一次。另外,也可以考虑使用自定义的批量处理方式(如使用MyBatis的批量执行器)。相关问题:1.MyBatisPlus如何配置主键策略?2.如何优化MyBatisPlus的批量插入性能?3.在MyBatisPlus中,如何判断`saveOrUpdateBatch`操作插入还是更新?4.如何处理批量操作中的主键冲突异常?5.MyBatisPlus批量操作时如何获取受影响的行数?</think>### MyBatisPlus `saveOrUpdateBatch` 获取主键 ID 的解决方案 #### 🔑 核心原理 MyBatisPlus 的 `saveOrUpdateBatch` 方法执行后,**新插入记录的数据库自主键会自动回填到实体对象的主键属性中**。但需满足以下条件: ```java public class User { @TableId(value = "id", type = IdType.AUTO) // ✅ 关键配置 private Long id; // 主键属性 } ``` #### 📝 实现步骤 ##### 1. 配置实体类主键策略 ```java @Data public class SysUser { @TableId(value = "id", type = IdType.AUTO) // ⚠️ 必须指定为AUTO private Long id; // 主键字段 // 其他字段... } ``` ##### 2. 调用方法并获取主键 ```java List<SysUser> userList = new ArrayList<>(); // 添加新对象(主键为null) userList.add(new SysUser(..., null)); // 添加需更新的对象(主键) userList.add(new SysUser(..., 1001L)); // 执行批量操作 userService.saveOrUpdateBatch(userList); // 获取ID:遍历检查插入的对象 for (SysUser user : userList) { if (user.getId() != null) { System.out.println("生成的自ID: " + user.getId()); } } ``` #### ⚠️ 注意事项 1. **主键策略必须正确** 确保 `@TableId(type = IdType.AUTO)`,错误配置会导致主键不回填(参考引用[2]) 2. **仅插入操作回填主键** 更新操作不会修改原主键,需通过主键是否为 `null` 区分: - ✅ **插入对象**:执行前 `id=null` → 执行后 `id=自` - ⛔ **更新对象**:执行前 `id≠null` → 执行后 `id` 不变 3. **批量大小影响性能** 超大列表需分批处理(参考引用[1]建议): ```java // 每500条分批执行 List<List<SysUser>> partitions = Lists.partition(userList, 500); partitions.forEach(userService::saveOrUpdateBatch); ``` #### 💡 高级场景处理 ##### 混合插入/更新的主键收集 ```java List<Long> newIds = userList.stream() .filter(u -> u.getId() == null) // 筛选新对象 .map(SysUser::getId) // 获取回填ID .collect(Collectors.toList()); ``` ##### 避免主键冲突(参考引用[3]) ```java // 确保更新对象主键存在 userService.saveOrUpdateBatch(userList, 1000, // 分批大小 (sqlSession, entity) -> { // 自定义冲突处理逻辑 if (existsInDb(entity)) { sqlSession.update("updateUser", entity); } else { sqlSession.insert("insertUser", entity); } } ); ``` #### 🔍 验证是否成功 启用 MyBatis 日志检查 SQL: ```yaml # application.yml logging: level: com.micro.system.mapper: DEBUG ``` 日志中应出现: ```sql INSERT INTO sys_user(...) VALUES (...) -- 插入语句 -- 后跟: RETURNING id 或 SELECT LAST_INSERT_ID() ``` #### 🌟 总结流程 ```mermaid graph TD A[准备实体列表] --> B{主键是否为null?} B -->|null| C[执行插入操作] B -->|非null| D[执行更新操作] C --> E[数据库生成自ID] E --> F[ID回填到实体对象] D --> G[保持原主键不变] F --> H[遍历获取ID] G --> H ``` #### 📚 相关问题 1. MyBatisPlus 如何实现批量插入时的主键回填机制? 2. 使用 `saveOrUpdateBatch` 时如何避免主键冲突异常? 3. 非自主键(如 UUID)如何通过批量操作获取ID? 4. 如何优化 MyBatisPlus 批量操作的性能? 5. 混合插入/更新操作后如何区分哪些记录新增的?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值