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开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
-
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></user>,Mapper 接口方法仍为void insertBatch(List<user> list)</user> - 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更可靠










