当前位置: 首页 > article >正文

Java + Spring Boot + Mybatis 插入数据后,获取自增 id 的方法

在 MyBatis 中使用 useGeneratedKeys="true" 获取新插入记录的自增 ID 值,可通过以下步骤实现:

1. 配置 Mapper XML

在插入语句的 <insert> 标签中设置:

xml

复制

下载

运行

<insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">INSERT INTO user(name, email)VALUES (#{name}, #{email})
</insert>
  • useGeneratedKeys="true":启用数据库生成的主键(如自增 ID)。

  • keyProperty="id":将生成的主键值赋给参数对象(如 User 对象)的 id 属性。


2. 定义实体类

确保实体类有对应的属性(与 keyProperty 一致):

java

复制

下载

public class User {private Long id; // 属性名必须与 keyProperty 匹配private String name;private String email;// Getter & Setter
}

3. 调用 Mapper 方法

插入后,自动填充的 ID 会直接赋给传入的实体对象:

java

复制

下载

User newUser = new User();
newUser.setName("John");
newUser.setEmail("john@example.com");// 执行插入(返回的是影响行数,非 ID)
int rows = userMapper.insertUser(newUser); // 插入后,自增 ID 已注入 newUser 的 id 属性
Long newId = newUser.getId(); // ✅ 直接获取
System.out.println("新记录的 ID:" + newId);

关键点说明

  1. keyProperty 必须匹配实体属性名
    如实体属性为 userId,则需配置 keyProperty="userId"

  2. 支持批量插入(MyBatis 3.3.1+)
    配置 keyProperty 为集合元素的属性:

    xml

    复制

    下载

    运行

    <insert id="insertUsers" useGeneratedKeys="true" keyProperty="id">INSERT INTO user(name) VALUES <foreach collection="list" item="user" separator=",">(#{user.name})</foreach>
    </insert>

    调用后,每个对象的 id 都会被赋值:

    java

    复制

    下载

    List<User> users = Arrays.asList(new User("A"), new User("B"));
    userMapper.insertUsers(users);
    users.forEach(u -> System.out.println(u.getId())); // 输出所有新 ID
  3. 数据库兼容性

    • MySQL/SQL Server:直接支持 useGeneratedKeys

    • Oracle:需用 <selectKey> 配合序列(非本方案范畴)。


常见问题

  • 获取值为 null
    检查 keyProperty 是否与实体属性名一致,或数据库是否真的生成了自增 ID。

  • 批量插入无效?
    确保 MyBatis 版本 ≥ 3.3.1,且 keyProperty 指向集合元素的属性(如 id)。

通过此方案,插入后无需额外查询,ID 值直接注入对象属性,高效简洁。

在 MyBatis 中,keyProperty 可以指定为参数对象中的任意属性路径(包括嵌套对象或 Map 的键值),不一定必须是主实体对象的属性。以下是几种灵活用法:


1. 指定参数对象的嵌套属性

若参数是一个包含 ID 容器的复合对象:

java

复制

下载

public class InsertParam {private User user;private Long generatedId; // 专门接收 ID 的属性// Getter & Setter
}

Mapper XML 配置:

xml

复制

下载

运行

<insert id="insertUser" parameterType="InsertParam" useGeneratedKeys="true" keyProperty="generatedId">INSERT INTO user(name) VALUES (#{user.name})
</insert>

插入后获取:

java

复制

下载

InsertParam param = new InsertParam();
param.setUser(new User("Alice"));
userMapper.insertUser(param);Long newId = param.getGeneratedId(); // ✅ 从专用属性获取

2. 使用 Map 参数接收

直接通过 Map 传递参数并接收 ID:

xml

复制

下载

运行

<insert id="insertUser" parameterType="map"useGeneratedKeys="true" keyProperty="resultId">INSERT INTO user(name) VALUES (#{name})
</insert>

Java 调用:

java

复制

下载

Map<String, Object> params = new HashMap<>();
params.put("name", "Bob");userMapper.insertUser(params);Long newId = (Long) params.get("resultId"); // ✅ 从 Map 获取

3. 多参数场景(结合 @Param

当方法有多个参数时,用 @Param 指定命名空间:

java

复制

下载

int insertUser(@Param("user") User user,@Param("idHolder") Map<String, Long> idHolder // 专门存 ID 的 Map
);

Mapper XML 配置:

xml

复制

下载

运行

<insert id="insertUser" useGeneratedKeys="true" keyProperty="idHolder.id">INSERT INTO user(name) VALUES (#{user.name})
</insert>

插入后获取:

java

复制

下载

Map<String, Long> idHolder = new HashMap<>();
User user = new User("Charlie");userMapper.insertUser(user, idHolder);Long newId = idHolder.get("id"); // ✅ 从独立 Map 获取

关键规则

  1. 路径匹配原则
    keyProperty 的值是 OGNL 表达式,需严格匹配参数对象的属性路径:

    • 单参数:直接写属性名(如 generatedId

    • 多参数:用 @Param 别名前缀(如 idHolder.id

  2. 批量插入场景
    批量操作时 keyProperty 需指向集合元素的属性(不支持外部容器):

    xml

    复制

    下载

    运行

    <!-- 正确:ID 注入到每个元素的 id 属性 -->
    <insert id="batchInsert" useGeneratedKeys="true" keyProperty="id">INSERT INTO user(name) VALUES <foreach item="item" collection="list" separator=",">(#{item.name})</foreach>
    </insert>
  3. 常见问题

    • 属性未注入? 检查 keyProperty 路径是否存在 setter 方法

    • 返回 null 确保数据库自增 ID 已生效(如 MySQL 的 AUTO_INCREMENT


使用建议

  • 专用 ID 容器:推荐用独立 Map 或 DTO 属性接收 ID,避免污染实体对象

  • 明确路径:多参数时用 @Param 定义清晰命名空间(如 keyProperty="holder.id"

  • 事务安全:插入后立即从参数对象中获取 ID,确保在同一事务内

当 Mapper 方法有多个参数时,MyBatis 无法确定将生成的自增 ID 注入到哪个参数中。以下是详细解决方案:

错误原因分析

复制

下载

Cause: org.apache.ibatis.executor.ExecutorException: 
Could not determine which parameter to assign generated keys to.
Note that when there are multiple parameters, 'keyProperty' must include the parameter name
  • 当 Mapper 方法有多个参数时,必须使用 参数名前缀 明确指定注入位置

  • 您当前配置的 keyProperty="generatedId" 缺少参数名前缀

  • MyBatis 找到的可用参数:[generatedId, ckDetailId, param1, param2]


解决方案:添加参数名前缀

方法 1:使用 @Param 注解明确命名参数

java

复制

下载

// Mapper 接口方法
int insertRecord(@Param("data") Map<String, Object> data,       // 数据参数@Param("idHolder") Map<String, Long> idHolder  // 专门接收ID的参数
);

xml

复制

下载

运行

<!-- Mapper XML 配置 -->
<insert id="insertRecord" useGeneratedKeys="true" keyProperty="idHolder.generatedId">  <!-- 添加参数名前缀 -->INSERT INTO your_table(...) VALUES (#{data.field1}, #{data.field2})
</insert>
方法 2:使用 MyBatis 默认参数名(不推荐)

xml

复制

下载

运行

<insert id="insertRecord" useGeneratedKeys="true" keyProperty="param2.generatedId">  <!-- 使用paramN格式 -->...
</insert>

参数索引从1开始:param1=第一个参数, param2=第二个参数


完整示例代码

1. Mapper 接口

java

复制

下载

public interface YourMapper {int insertRecord(@Param("detail") YourEntity entity,         // 实体参数@Param("idHolder") Map<String, Long> holder // ID容器参数);
}
2. Mapper XML

xml

复制

下载

运行

<insert id="insertRecord" useGeneratedKeys="true"keyProperty="idHolder.generatedId">  <!-- 关键:带前缀的keyProperty -->INSERT INTO your_table(name, ck_detail_id)VALUES (#{detail.name}, #{detail.ckDetailId})
</insert>
3. 调用代码

java

复制

下载

// 准备参数
YourEntity entity = new YourEntity("test", 1001);
Map<String, Long> idHolder = new HashMap<>();  // 专门接收ID// 执行插入
mapper.insertRecord(entity, idHolder); // 获取自增ID (注意键名与XML中一致)
Long newId = idHolder.get("generatedId"); 
System.out.println("Generated ID: " + newId);

关键注意事项

  1. 前缀必须匹配 @Param 值
    keyProperty="idHolder.generatedId" 对应:

    • idHolder → @Param("idHolder")

    • generatedId → Map中的键名

  2. Map 接收 vs 对象属性

    xml

    复制

    下载

    运行

    <!-- 如果使用对象属性接收 -->
    keyProperty="detail.id"  <!-- 注入到实体对象的id属性 --><!-- 如果使用Map接收 -->
    keyProperty="idHolder.generatedId"  <!-- 注入到Map的generatedId键 -->
  3. 批量插入特殊处理
    批量操作时仍需注入到集合元素内:

    xml

    复制

    下载

    运行

    <insert id="batchInsert" useGeneratedKeys="true" keyProperty="id">INSERT ... <!-- 无法注入到外部参数 -->
    </insert>

常见错误排查

错误现象解决方案
返回null检查数据库自增列是否生效
Invalid bound statement检查keyProperty前缀是否匹配@Param
批量插入ID未注入确保keyProperty指向集合元素的属性
Oracle数据库不生效需使用<selectKey>替代

建议:对多参数场景始终使用 @Param + 前缀的 keyProperty,避免依赖 paramN 隐式命名

相关文章:

Java + Spring Boot + Mybatis 插入数据后,获取自增 id 的方法

在 MyBatis 中使用 useGeneratedKeys"true" 获取新插入记录的自增 ID 值&#xff0c;可通过以下步骤实现&#xff1a; 1. 配置 Mapper XML 在插入语句的 <insert> 标签中设置&#xff1a; xml 复制 下载 运行 <insert id"insertUser" para…...

【Linux应用】Linux系统日志上报服务,以及thttpd的配置、发送函数

【Linux应用】Linux系统日志上报服务&#xff0c;以及thttpd的配置、发送函数 文章目录 thttpd服务安装thttpd配置thttpd服务thttpd函数日志效果和文件附录&#xff1a;开发板快速上手&#xff1a;镜像烧录、串口shell、外设挂载、WiFi配置、SSH连接、文件交互&#xff08;RADX…...

Nginx 事件驱动理解

在做埋点采集服务的过程中&#xff0c;主要依靠openresty加lua脚本来实现采集。高并发还是主要依靠nginx来实现。而其核心就是事件驱动/多路io复用&#xff08;epoll机制&#xff09;&#xff0c;不同的linux服务器都有对应的实现方式。 而epoll机制就是&#xff0c;应用启动的…...

Jmeter(四) - 如何在jmeter中创建网络测试计划

1.简介 如何创建基本的 测试计划来测试网站。您将创建五个用户&#xff0c;这些用户将请求发送到JMeter网站上的两个页面。另外&#xff0c;您将告诉用户两次运行测试。 因此&#xff0c;请求总数为&#xff08;5个用户&#xff09;x&#xff08;2个请求&#xff09;x&#xff…...

Amazon RDS on AWS Outposts:解锁本地化云数据库的混合云新体验

在混合云架构成为企业数字化转型标配的今天&#xff0c;如何在本地数据中心享受云数据库的强大能力&#xff0c;同时满足数据本地化、低延迟访问的严苛需求&#xff1f;Amazon RDS on AWS Outposts 给出了完美答案——将AWS完全托管的云数据库服务无缝延伸至您的机房&#xff0…...

2025年上海市“星光计划”第十一届职业院校技能大赛 网络安全赛项技能操作模块样题

2025年上海市“星光计划”第十一届职业院校技能大赛 网络安全赛项技能操作模块样题 &#xff08;二&#xff09;模块 A&#xff1a;安全事件响应、网络安全数据取证、应用安全、系统安全任务一&#xff1a;漏洞扫描与利用:任务二&#xff1a;Windows 操作系统渗透测试 :任务三&…...

jieba实现和用RNN实现中文分词的区别

Jieba 分词和基于 RNN 的分词在技术路线、实现机制、性能特点上有显著差异&#xff0c;以下是核心对比&#xff1a; 1. 技术路线对比 维度Jieba 分词RNN 神经网络分词范式传统 NLP&#xff08;规则 统计&#xff09;深度学习&#xff08;端到端学习&#xff09;核心依赖词典…...

android计算器代码

本次作业要求实现一个计算器应用的基础框架。以下是布局文件的核心代码&#xff1a; <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"andr…...

leetcode 386. 字典序排数 中等

给你一个整数 n &#xff0c;按字典序返回范围 [1, n] 内所有整数。 你必须设计一个时间复杂度为 O(n) 且使用 O(1) 额外空间的算法。 示例 1&#xff1a; 输入&#xff1a;n 13 输出&#xff1a;[1,10,11,12,13,2,3,4,5,6,7,8,9]示例 2&#xff1a; 输入&#xff1a;n 2…...

Modbus转ETHERNET IP网关:快速冷却系统的智能化升级密钥

现代工业自动化系统中&#xff0c;无锡耐特森Modbus转Ethernet IP网关MCN-EN3001扮演着至关重要的角色。通过这一技术&#xff0c;传统的串行通讯协议Modbus得以在更高速、更稳定的以太网环境中运行&#xff0c;为快速冷却系统等关键设施的自动化控制提供了强有力的支撑。快速冷…...

Linux——TCP和UDP

一、TCP协议 1.特点 TCP提供的是面向连接、可靠的、字节流服务。 2.编程流程 &#xff08;1&#xff09;服务器端的编程流程 ①socket() 方法创建套接字 ②bind()方法指定套接字使用的IP地址和端口。 ③listen()方法用来创建监听队列。 ④accept()方法处理客户端的连接…...

比较数据迁移后MySQL数据库和PostgreSQL数据仓库中的表

设计一个MySQL数据库和PostgreSQL数据库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较两…...

云原生技术驱动 IT 架构现代化转型:企业实践与落地策略全解

&#x1f4dd;个人主页&#x1f339;&#xff1a;慌ZHANG-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 一、背景&#xff1a;IT 架构演进的战略拐点 过去十年&#xff0c;企业 IT 架构经历了从传统集中式架构到分布式架构的转型。进入云计算…...

Android Settings 数据库生成、监听与默认值配置

一、Settings 数据库生成机制​ ​传统数据库生成&#xff08;Android 6.0 前&#xff09;​​ ​路径​&#xff1a;/data/data/com.android.providers.settings/databases/settings.db​创建流程​&#xff1a; ​SQL 脚本初始化​&#xff1a;通过 sqlite 工具创建数据库文件…...

SeaweedFS S3 Spring Boot Starter

SeaweedFS S3 Spring Boot Starter 源码特性环境要求快速开始1. 添加依赖2. 配置文件3. 使用方式方式一&#xff1a;注入服务类方式二&#xff1a;使用工具类 API 文档SeaweedFsS3Service 主要方法SeaweedFsS3Util 工具类方法 配置参数运行测试构建项目注意事项集成应用更多项目…...

Monorepo架构: 项目管理模式对比与考量

关于 monorepo 相关概念及项目管理模式 在软件开发中&#xff0c;尤其是前端项目&#xff0c;我们会涉及到不同的项目管理模式&#xff0c;这里先介绍几个重要的概念“monorepo”是当前较为热门的一种项目管理方式&#xff0c;虽然很多人可能听说过&#xff0c;但可能在实际项…...

智慧城市项目总体建设方案(Word700页+)

1 背景、现状和必要性 1.1 背景 1.1.1 立项背景情况 1.1.2 立项依据 1.2 现状 1.2.1 党建体系运行现状 1.2.2 政务体系运行现状 1.2.3 社会治理运行现状 1.2.4 安全监管体系现状 1.2.5 环保体系运行现状 1.2.6 城建体系运行现状 1.2.7 社区体系运行现状 1.2.8 园区…...

详解ZYNQ中的 RC 和 EP

详解ZYNQ中的 RC 和 EP 一、ZYNQ FPGA 开发板基础&#xff08; ZC706 &#xff09; 1. 核心特点 双核大脑 灵活积木&#xff1a; ZC706 集成了 ARM Cortex-A9 双核处理器&#xff08;相当于电脑 CPU&#xff09;和 FPGA 可编程逻辑单元&#xff08;相当于可自定义的硬件积木…...

CSP信奥赛C++常用系统函数汇总

# CSP信奥赛C常用系统函数汇总## 一、输入输出函数### 1. cin / cout&#xff08;<iostream>&#xff09; cpp int x; cin >> x; // 输入 cout << x << endl;// 输出 优化&#xff1a;ios::sync_with_stdio(false); 可提升速度 2. scanf() /…...

Qt Quick Dialogs模块功能及架构

Qt Quick Dialogs 是 Qt Quick 的一个附加模块&#xff0c;提供了一套用于创建和使用系统对话框的 QML 类型。在 Qt 6.0 中&#xff0c;这个模块经过了重构和增强。 一、主要功能和特点 1. 对话框类型 Qt Quick Dialogs 在 Qt 6.0 中提供了以下标准对话框类型&#xff1a; …...

Unity基础-Mathf相关

Unity基础-Mathf相关 一、Mathf数学工具 概述 Mathf是Unity中封装好用于数学计算的工具结构体&#xff0c;提供了丰富的数学计算方法&#xff0c;特别适用于游戏开发场景。它是Unity开发中最常用的数学工具之一&#xff0c;能够帮助我们处理各种数学计算和插值运算。 Mathf…...

STM32CubeMX-H7-19-ESP8266通信(中)--单片机控制ESP8266实现TCP地址通信

前言 上篇文章我们已经能够使用串口助手实现esp8266的几种通信&#xff0c;接下来我们使用单片机控制实现。这篇文章会附带教程&#xff0c;增加.c和,.h&#xff0c;把串口和定时器放到对应的编号&#xff0c;然后调用初始化就可以使用了。 先讲解&#xff0c;然后末尾再放源码…...

ubuuntu24.04 编译安装 PostgreSQL15.6+postgis 3.4.2 + pgrouting 3.6.0 +lz4

文章目录 下载基础包下载源码包编译 PG编译 postgis编译安装 pgrouting下载源码包配置编译参数编译安装 初始化数据库建表并检查列是否使用了 lz4 压缩算法检查 postgis 与 pgrouting 是否可以成功创建 下载基础包 sudo apt update && sudo apt upgrade -y sudo apt i…...

【汇编逆向系列】四、函数调用包含单个参数之Double类型-mmword,movsd,mulsd,addsd指令,总结汇编的数据类型

一、汇编代码 上一节开始&#xff0c;讲到了很多debug编译独有的汇编方式&#xff0c;为了更好的区分release的编译器优化和debug的区别&#xff0c;从本章节开始将会提供debug和release的汇编用作对比 Debugb编译 single_double_param:00000000000000A0: F2 0F 11 44 24 08…...

【AI学习】wirelessGPT多任务无线基础模型摘要

收看了关于WirelessGPT多任务无线基础模型的演讲视频&#xff0c;边做一个记录。 应该说&#xff0c;在无线通信大模型的探索方面&#xff0c;有一个非常有益的尝试。 在沈学明院士带领下开展 https://www.chaspark.com/#/live/1125484184592834560...

docker 部署redis集群 配置

docker的网络模式 网桥模式每次重启容器都有可能导致容器ip地址变化&#xff0c;需要固定ip的自己自定义网络&#xff0c;这里介绍的是默认网络模式 docker创建容器 docker run --name redis6379 -p 6379:6379 -p 16379:16379 -v /etc/redis/redis6379:/etc/redis -d --r…...

Ansys Maxwell:线圈和磁体的静磁 3D 分析

本博客展示了如何在 Ansys Maxwell 中执行静磁 3D 分析&#xff0c;以计算载流线圈和永磁体之间相互作用产生的扭矩。在这个例子中&#xff0c;线圈中的电流产生一个沿 Y 轴指向的磁场&#xff0c;而永磁体沿 X 轴被磁化。这种配置导致围绕 Z 轴的扭矩。分步工作流程包括构建几…...

android 之 KeyguardService

一、功能定位与核心作用 KeyguardService 是 Android 锁屏功能的核心服务&#xff0c;负责管理设备锁屏界面&#xff08;如密码、图案、指纹等验证流程&#xff09;&#xff0c;并协调系统安全策略与用户交互。主要职责包括&#xff1a; 锁屏状态管理 控制锁屏界面的显示/隐藏…...

compose 组件 ---无ui组件

在 Jetpack Compose 中&#xff0c;确实存在不直接参与 UI 渲染的组件&#xff0c;它们主要用于逻辑处理、状态管理或副作用控制。这些组件虽然没有视觉界面&#xff0c;但在架构中扮演重要角色。以下是常见的非 UI 组件及其用途&#xff1a; 1. 无 UI 的 Compose 组件分类 (…...

【计算机网络】SDN

SDN这种新型网络体系结构的核心思想&#xff1a;把网络的控制层面与数据层面分离&#xff0c;而让控制层面利用软件来控制数据层面中的许多设备。 OpenFlow协议可以被看成是SDN体系结构中控制层面与数据层面之间的通信接口。 在SDN中取代传统路由器中转发表的是“流表”&…...