MyBatis 插入时获取自增主键 ID 的核心是 useGeneratedKeys + keyProperty(MySQL)或 selectKey/RETURNING(PostgreSQL 等),需确保 SQL 不手动赋值主键、keyProperty 与实体 setter 匹配、驱动版本兼容。

MyBatis 在插入数据时获取数据库自增主键 ID,核心是通过 useGeneratedKeys 和 keyProperty(或 keyColumn)配合实现,无需额外查询。不同数据库(如 MySQL、PostgreSQL)略有差异,但主流用法一致。
MySQL 场景:使用 useGeneratedKeys
适用于 MySQL 的 AUTO_INCREMENT 主键。Mapper XML 中配置如下:
<!-- 注意:不要写 INSERT INTO ... VALUES (null, ...),让数据库生成 -->
INSERT INTO user (name, email) VALUES (#{name}, #{email})
</insert>
Java 调用后,传入的对象(如 User)的 id 字段会被自动赋值为新生成的主键:
User user = new User("张三", "zhangsan@example.com");
userMapper.insertUser(user);
System.out.println(user.getId()); // 输出刚插入的自增 ID
PostgreSQL / SQL Server 等:使用 selectKey
PostgreSQL 不支持 useGeneratedKeys(驱动限制),需用 <selectKey> 显式获取序列值:
立即学习“Java免费学习笔记(深入)”;
<insert id="insertUser"><selectKey keyProperty="id" resultType="long" order="BEFORE">
SELECT nextval('user_id_seq')
</selectKey>
INSERT INTO user (id, name, email) VALUES (#{id}, #{name}, #{email})
</insert>
注意:
- order="BEFORE" 表示先取 ID 再插入,适合带默认序列的场景;
- 若用 RETURNING id(PostgreSQL 9.1+),可设 order="AFTER" 并省略显式赋值:
INSERT INTO user (name, email) VALUES (#{name}, #{email}) RETURNING id
</insert>
此时需在 Mapper 接口中声明返回类型为 long 或封装类,并确保驱动支持(如 PostgreSQL JDBC 42.2+)。
实体类与字段命名要匹配
keyProperty 必须与 Java 对象中的属性名完全一致(区分大小写),且该属性要有 public setter 方法。例如:
- 实体类中字段叫
id→keyProperty="id" - 字段叫
userId→keyProperty="userId" - 数据库列名为
user_id,但 Java 属性仍为userId,无需配keyColumn(除非列名和属性名不一致且需显式映射)
注意事项与常见问题
以下情况会导致主键未回填:
- SQL 中手动给主键赋了值(如
VALUES (1, ...)),数据库跳过自增逻辑 -
keyProperty拼写错误或对应属性无 setter - MySQL 驱动版本过低(建议 8.0+),或连接 URL 缺少
useSSL=false&serverTimezone=UTC等必要参数 - 执行的是批量插入(
insertBatch),useGeneratedKeys可能只返回第一个 ID,需改用selectKey或数据库原生批量返回支持


















