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 隐式命名

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/83463.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Meta发布V-JEPA 2世界模型及物理推理新基准,推动AI在物理世界中的认知与规划能力

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

触觉智能RK3576核心板工业应用之软硬件全国产化,成功适配开源鸿蒙OpenHarmony5.0

在全球科技竞争加剧和供应链安全日益重要的背景下&#xff0c;实现关键软硬件的全国产化替代已成为国家战略和产业共识。在这一背景下&#xff0c;触觉智能推出RK3576核心板,率先适配开源鸿蒙OpenHarmony5.0操作系统&#xff0c;真正实现了从芯片到操作系统的全栈国产化方案&am…

前端基础知识ES6系列 - 01(var、let、const之间的区别)

一、var 在ES5中&#xff0c;顶层对象的属性和全局变量是等价的&#xff0c;用var声明的变量既是全局变量&#xff0c;也是顶层变量 注意&#xff1a;顶层对象&#xff0c;在浏览器环境指的是window对象&#xff0c;在 Node 指的是global对象 var a 10; console.log(window…

Python Docker 镜像构建完整指南:从基础到优化

Python 是一门广泛使用的编程语言,在容器化环境中,构建和使用 Python 镜像是非常常见的任务。本文将提供一个完整的指南,包括选择基础镜像、制作流程、不同场景下的应用、安全性最佳实践以及镜像优化策略。 1. 选择合适的基础镜像 1.1 官方 Python 镜像 Docker Hub 提供了…

【狂飙AGI】第1课:大模型概述

目录 &#xff08;一&#xff09;大模型概念解析&#xff08;二&#xff09;大模型发展历程&#xff08;三&#xff09;大模型发展现状&#xff08;1&#xff09;OpenAI&#xff08;2&#xff09;微软&#xff08;3&#xff09;谷歌&#xff08;4&#xff09;Meta &#xff08;…

vite ts 配置使用@ 允许js

1.vite.config.ts 配置 import { defineConfig } from vite import vue from vitejs/plugin-vue import { fileURLToPath, URL } from node:url import setup_extend from vite-plugin-vue-setup-extend// https://vite.dev/config/ export default defineConfig({plugins: …

使用Ollama+open-webui搭建本地AI模型

本地搭建AI模型 说明&#xff1a;1、下载Ollama2、下载模型3、pip安装open-webui&#xff08;不推荐&#xff09;1、Python版本不对应2、下载wheels失败 4、docker安装open-webui 说明&#xff1a; 在windows上搭建本地AI&#xff0c;使用Ollamaopen-webui的方式&#xff0c;可…

第 87 场周赛:比较含退格的字符串、数组中的最长山脉、一手顺子、访问所有节点的最短路径

Q1、[简单] 比较含退格的字符串 1、题目描述 给定 s 和 t 两个字符串&#xff0c;当它们分别被输入到空白的文本编辑器后&#xff0c;如果两者相等&#xff0c;返回 true 。# 代表退格字符。 **注意&#xff1a;**如果对空文本输入退格字符&#xff0c;文本继续为空。 示例 …

linux安装阿里DataX实现数据迁移

目录 下载datax工具包(如果下载慢&#xff0c;请尝试其他国内镜像站或其他网站下载相应资源) 解压工具包到当前目录里 接着进入conf配置目录并创建一个myjob.json&#xff08;临时测试json&#xff09;&#xff0c;myjob.json内容如下&#xff0c;用于模拟test库tab1表数据同…

C++ 引用介绍

很好&#xff01;既然你有 C 的基础&#xff0c;那么理解 C 的「引用&#xff08;reference&#xff09;」会容易很多。我们来一步步讲清楚这个概念。 &#x1f31f; 一句话总结&#xff1a; C 引用&#xff08;reference&#xff09;就是已存在变量的“别名”&#xff0c;它不…

学习笔记086——@PostConstruct注解和InitializingBean接口的使用

文章目录 1、PostConstruct注解1.1 介绍1.2 用法1.3 场景 2、InitializingBean接口2.1 介绍2.2 用法 1、PostConstruct注解 1.1 介绍 PostConstruct 是 Java EE/Jakarta EE 中的一个注解&#xff0c;用于标记一个方法在依赖注入完成后执行初始化操作。它通常与 Spring 框架一…

考研系列—408真题操作系统篇(2015-2019)

目录 # 2015年 1.死锁处理 (1)预防死锁 (2)避免死锁 (3)死锁检测和解除 2.请求分页系统的页面置换策略、页面置换策略 3.页、页框、页表,基本分页系统 # 2016年 1.异常、中断 2.页置换算法 3.进程的互斥操作 4.SPOOLing技术(从软件方面实现设备共享) 5.一定要牢记…

argocd部署cli工具并添加k8s集群

先决条件: 1.已经有k8s集群,(网上一万种部署方式,这里我使用的是kubekey部署的),也埋了个坑,后面说明. 2.已经部署好argocd,并验证web已经可以访问.参见 k8s部署argocd-CSDN博客 部署客户端工具, 这里我是从web页面上直接下载的对应版本的cli工具. 打开已经部署好的argoc…

打卡day52

简单cnn 借助调参指南进一步提高精度 基础CNN模型代码 import tensorflow as tf from tensorflow.keras import layers, models from tensorflow.keras.datasets import cifar10 from tensorflow.keras.utils import to_categorical# 加载数据 (train_images, train_labels),…

OpenGL ES绘制3D图形以及设置视口

文章目录 关于 glDrawElements基本概念使用场景mode 绘制模式type 索引数据类型indices 索引缓冲区工作原理绘制正方体实例 视口透视投影&#xff08;Perspective Projection&#xff09;正交投影&#xff08;Orthographic Projection&#xff09;正交投影和透视投影对比 关于 …

【SAS求解多元回归方程】REG多元回归分析-多元一次回归

多元一次回归是一种统计方法&#xff0c;用于分析多个自变量&#xff08;解释变量&#xff09;与一个因变量&#xff08;响应变量&#xff09;之间的线性关系。 目录 【示例】 基本语法 SAS代码 参数估计 方差分析 回归统计量 y的拟合诊断 y的回归变量值 【示例】 设Y…

卡通幼儿园教育通用可爱PPT模版分享

幼儿园教育通用PPT模版&#xff0c;教育教学PPT模版&#xff0c;卡通教育PPT模版&#xff0c;可爱卡通教学课件PPT模版&#xff0c;小清新动物卡通通用PPT模版&#xff0c;教学说课通用PPT模版&#xff0c;开学季PPT模版&#xff0c;国学颂歌PPT模版&#xff0c;可爱简约风PPT模…

力扣HOT100之技巧:75. 颜色分类

这道题实际上就是让我们不用sort()函数来实现对原数组的排序&#xff0c;这里我直接使用快速排序对原数组进行排序了&#xff0c;也是复习一下基于快慢指针的快速排序写法。面试手撕快排的思路参考这个视频。 用时击败100%&#xff0c;还行。下面直接贴代码。 class Solution …

离线部署openstack 2024.1 keystone

控制节点身份服务 离线下载 apt-get install --download-only keystone python3-openstackclient apache2 libapache2-mod-wsgi-py3mkdir /controller/keystone mv /var/cache/apt/archives/*.deb /controller/keystone/ dpkg -i /controller/keystone/*.deb在一个控制节点操…

帆软 BI 从入门到实战全攻略(一):安装激活与添加数据

一、帆软 BI 产品概述​ 在当今大数据时代&#xff0c;数据分析与可视化成为企业洞察业务、驱动决策的关键利器。帆软软件有限公司作为中国专业的大数据 BI 和分析平台提供商&#xff0c;自 2006 年成立以来&#xff0c;凭借其在商业智能和数据分析领域的深耕细作&#xff0c;…