MyBatis插入后获取自增ID的核心是通过useGeneratedKeys+keyProperty将数据库生成的ID自动回填到Java对象属性中,而非返回值;需数据库主键自增且JDBC驱动支持getGeneratedKeys(),实体类须有对应getter/setter。

MyBatis 在插入数据后获取自增主键 ID,核心是让框架把数据库生成的 ID 自动回填到 Java 对象里,而不是靠额外查一次数据库。关键在于配置方式和数据库支持,不是所有场景都适用同一种写法。
useGeneratedKeys + keyProperty(推荐,MySQL/PostgreSQL 等常用)
这是最简洁、性能最好的方式,依赖 JDBC 的 getGeneratedKeys() 方法,无需额外 SQL 查询。
-
前提条件:数据库表主键必须设为自增(如 MySQL 的
AUTO_INCREMENT),且 JDBC 驱动支持该特性 -
XML 写法:
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">INSERT INTO user(name) VALUES(#{name})</insert> -
注解写法:
@Insert("INSERT INTO user(name) VALUES(#{name})")@Options(useGeneratedKeys = true, keyProperty = "id") -
注意点:Java 实体类中必须有
id字段的 getter/setter;插入后直接读取对象的id属性即可,方法本身无返回值
selectKey(通用性强,适配 Oracle 等不支持 getGeneratedKeys 的库)
通过显式 SQL 获取刚插入的主键,灵活性高,但多一次查询,高并发下需注意 LAST_INSERT_ID() 或 @@identity 的会话隔离性。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
order="AFTER":先插入,再执行
SELECT LAST_INSERT_ID()(MySQL)或SELECT @@identity(SQL Server) - order="BEFORE":适用于序列(如 Oracle),先查序列值赋给对象,再插入(此时 SQL 中要引用该值)
-
示例:
<selectKey keyProperty="id" resultType="long" order="AFTER">SELECT LAST_INSERT_ID()</selectKey> -
适用场景:跨数据库兼容、需要控制主键生成逻辑、或底层驱动不支持
useGeneratedKeys
批量插入时怎么拿 ID?
MyBatis 支持批量插入并回填主键,但只对 useGeneratedKeys=true 有效,selectKey 不支持批量。
- 传入
List<User>,Mapper 接口方法仍为void insertBatch(List<User> list) - XML 中保持
useGeneratedKeys="true" keyProperty="id",MyBatis 会逐条设置每条记录的id - MySQL 5.7+ 和较新 JDBC 驱动下表现稳定;旧版本可能只返回第一条的 ID,需验证
常见踩坑提醒
看似简单,但实际容易出错的地方集中在配置和环境匹配上。
- 实体类字段名与
keyProperty不一致(比如字段叫userId却写成id) - 数据库没开自增,却用了
useGeneratedKeys—— 结果是id仍为 0 或 null - MySQL 使用 InnoDB 引擎但事务未提交,
LAST_INSERT_ID()在不同连接间不可见 - 多数据源或分库场景下,
selectKey可能指向错误的数据源,useGeneratedKeys更可靠

















