MyBatis插入后返回自增主键需同时配置useGeneratedKeys="true"和keyProperty="id"于<insert>标签内,keyProperty须匹配Java实体属性名且含public setter,数据库为InnoDB并设AUTO_INCREMENT,JDBC URL禁用rewriteBatchedStatements=true。

MyBatis 插入后返回自增主键,核心靠 useGeneratedKeys 和 keyProperty 配合 JDBC 的 getGeneratedKeys() 机制实现。配置看似简单,但错一个细节就拿不到 ID —— 对象的 id 字段还是 null 或 0。
必须写在 <insert> 标签上,不能放别处
useGeneratedKeys="true" 和 keyProperty="id" 必须作为属性直接写在 XML 中的 <insert> 标签内,不是写在 <mapper> 根节点、不是写在全局配置里,也不是写在 <selectKey> 里。
- ✅ 正确:
<insert id="insert" useGeneratedKeys="true" keyProperty="id"> - ❌ 错误:在
<configuration>里设useGeneratedKeys=true(无效) - ❌ 错误:只写
useGeneratedKeys="true"却漏了keyProperty(不报错,但不赋值)
keyProperty 填的是 Java 属性名,不是数据库字段名
keyProperty 的值必须严格匹配实体类中用于接收主键的字段名(驼峰命名),且该字段要有 public setter 方法。
- 如果实体类是
private Long userId;→keyProperty="userId"(Lombok@Data会生成setUserId()) - 如果字段是
private Long id;→keyProperty="id",不是"ID"、"_id"或"user_id" - 不支持嵌套,
keyProperty="address.id"会被忽略,不报错也不赋值
数据库和 JDBC 连接参数要配合
MySQL 下常见失效原因往往不在 MyBatis 配置,而在底层驱动行为:
立即学习“Java免费学习笔记(深入)”;
- 表引擎必须是
InnoDB,主键列必须声明为AUTO_INCREMENT - JDBC URL 中避免开启
rewriteBatchedStatements=true(它会合并多条 INSERT,导致只能取到第一个 ID)→ 推荐显式设为false或直接不配 - MySQL 5.7+ 和 8.0 默认支持批量获取 keys,但旧版驱动或连接池(如老 Druid)可能需额外配置
allowMultiQueries=true
批量插入也适用,但有前提
用 <foreach> 构建多值 INSERT 时,useGeneratedKeys="true" 同样生效,前提是:
- SQL 是单条多值语句(如
INSERT INTO t(name) VALUES (?,?),(?,?)) - 数据库和驱动支持批量返回生成键(MySQL 5.7+ OK)
- 每个传入对象的主键属性会按插入顺序依次回填(第1个对象拿到第1个 ID,以此类推)
- 实体类字段必须有规范 setter,比如
setId(Long),不能缺失


















