当前位置: 代码网 > it编程>编程语言>Java > MyBatis插入数据时获取生成主键的两种方法

MyBatis插入数据时获取生成主键的两种方法

2026年08月18日 Java 我要评论
引言在数据库设计中,主键自增(如 mysql 的 auto_increment)是最常见的场景。当我们在代码中插入一条数据时,往往需要立即获取这条数据在数据库中生成的唯一主键 id(例如用于后续关联操

引言

在数据库设计中,主键自增(如 mysql 的 auto_increment)是最常见的场景。当我们在代码中插入一条数据时,往往需要立即获取这条数据在数据库中生成的唯一主键 id(例如用于后续关联操作或返回给前端)。

mybatis 提供了两种强大的机制来实现这一点:usegeneratedkeys + keyproperty(推荐)和 <selectkey> 标签。下面我将从用法、底层原理到常见陷阱为你全面拆解。

一、方法一:usegeneratedkeys+keyproperty(最推荐)

这是 mybatis 最简洁、最直接的方式,利用 jdbc 底层的 statement.getgeneratedkeys() 方法实现。它适用于支持自动生成主键的数据库(mysql、sql server、postgresql 等)。

1. xml 映射文件配置

<insert> 标签中开启两个属性:

  • usegeneratedkeys="true":告诉 mybatis 使用 jdbc 的 getgeneratedkeys 方法获取主键。
  • keyproperty="id":指定将获取到的主键值赋值给实体类的哪个属性。
<insert id="insertcar" usegeneratedkeys="true" keyproperty="id">
    insert into t_car (car_num, brand, guide_price, produce_time, car_type)
    values (#{carnum}, #{brand}, #{guideprice}, #{producetime}, #{cartype})
</insert>

注意:这里无需在 sql 中写 id 字段,数据库会自动生成。

2. java 注解配置(对应接口)

如果使用注解开发,只需加上 @options 注解:

@insert("insert into t_car (car_num, brand) values (#{carnum}, #{brand})")
@options(usegeneratedkeys = true, keyproperty = "id")
int insertcar(car car);

3. 底层工作原理

  1. mybatis 执行 preparedstatement 时,会调用 connection.preparestatement(sql, statement.return_generated_keys)
  2. 执行 sql 后,jdbc 驱动通过 resultset generatedkeys = statement.getgeneratedkeys() 获取生成的主键结果集。
  3. mybatis 自动解析结果集,并通过反射将值注入到 car 对象的 id 属性中。

4. java 代码端使用

car car = new car();
car.setcarnum("1003");
car.setbrand("宝马");

// 执行插入
int rows = carmapper.insertcar(car);

// 此时 car 对象的 id 已经被自动赋值为数据库生成的主键!
system.out.println("插入后生成的id: " + car.getid()); // 输出: 插入后生成的id: 1

二、方法二:<selectkey>标签(更灵活)

当需要获取的值不是自增主键(如 uuid、oracle 的序列 sequence)时,或者在插入前就需要知道主键值,可以使用 <selectkey> 标签。

1. 应用场景:插入前获取 uuid(order="before")

<insert id="insertuser">
    <!-- 先执行查询,生成 uuid 并赋值给 user.id,再执行插入 -->
    <selectkey keyproperty="id" resulttype="string" order="before">
        select uuid()  <!-- mysql 生成 uuid 函数 -->
    </selectkey>
    insert into t_user (id, username) values (#{id}, #{username})
</insert>

2. 应用场景:oracle 序列自增(order="after")

oracle 没有自增主键,通常使用序列(sequence)。需要在插入后获取序列值,使用 order="after"

<insert id="insertemployee">
    <selectkey keyproperty="empid" resulttype="int" order="after">
        select seq_employee.currval from dual
    </selectkey>
    insert into t_employee (name, age) values (#{name}, #{age})
</insert>

注意order 属性控制查询语句的执行时机。

  • before:先执行 selectkey 查询,将结果设置给对象,再执行 insert
  • after:先执行 insert,再执行 selectkey 查询(用于查询当前序列值)。

三、特殊情况处理:批量插入时获取主键

当进行批量插入时,依然可以使用 usegeneratedkeys,mybatis 会为列表中的每一个对象都注入生成的主键。

xml 配置

<insert id="insertbatch" usegeneratedkeys="true" keyproperty="id">
    insert into t_car (car_num, brand) values
    <foreach collection="list" item="item" separator=",">
        (#{item.carnum}, #{item.brand})
    </foreach>
</insert>

java 测试

list<car> carlist = new arraylist<>();
carlist.add(new car("a001", "宝马"));
carlist.add(new car("a002", "奔驰"));

carmapper.insertbatch(carlist);

// 遍历列表,每个 car 对象都已填充了对应的自增 id
carlist.foreach(car -> system.out.println(car.getid()));
// 输出: 101, 102 (取决于当前自增值)

四、易错点与避坑指南(必看)

忘记写 keyproperty

  • 如果只写了 usegeneratedkeys="true" 而忘记指定 keyproperty="id",mybatis 虽然获取了主键,但不知道赋给谁,对象里的 id 依然为 null

keyproperty 写错属性名

  • 属性名必须与实体类中的字段名严格一致(如实体类是 carnum,配置 keyproperty="carnum" 就是错的,应该是 id)。

xml 中的 parametertypekeyproperty 的关系

  • keyproperty 指向的是 parametertype 指定类的属性。如果是多参数或 map,需要确保该 map 中包含对应的 key。

数据库驱动版本兼容性

  • 某些老旧的 mysql 驱动版本(如 5.1.6 之前)对 getgeneratedkeys 支持不完善,建议升级到较新版本。

<selectkey>resulttype

  • 必须在 <selectkey> 中明确指定 resulttype,否则 mybatis 无法确定返回值的类型,可能导致类型转换异常。

五、总结对比

特征usegeneratedkeys + keyproperty<selectkey> 标签
适用数据库mysql、sql server、postgresql(自增/identity)所有数据库(包括 oracle、uuid 等)
配置复杂度极简(仅两个属性)稍复杂(需配置查询语句和顺序)
获取时机执行 insert 之后可自定义 beforeafter
底层依赖jdbc 的 getgeneratedkeys() 方法执行额外的 sql 查询语句
推荐指数⭐⭐⭐⭐⭐(首选)⭐⭐⭐⭐(仅用于 oracle、uuid 等特殊场景)

六、最佳实践总结

  1. 使用 usegeneratedkeys 是最优雅的方式,它能确保你的代码与数据库驱动紧密结合,且仅执行一次 sql,性能最优。
  2. 在你的 carmapper.xml 中,请务必将 <insert> 修改为:
<insert id="insertcar" usegeneratedkeys="true" keyproperty="id">
    insert into t_car (car_num, brand, guide_price, produce_time, car_type)
    values (#{carnum}, #{brand}, #{guideprice}, #{producetime}, #{cartype})
</insert>
  1. 运行代码后,直接调用 car.getid() 即可拿到主键,彻底告别 select last_insert_id() 的繁琐操作!

以上就是mybatis插入数据时获取生成主键的两种方法的详细内容,更多关于mybatis插入数据时获取生成主键的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com