MyBatis实现主键返回功能的几种方式

 更新时间:2025年09月14日 11:35:06   作者:六七_Shmily  
在 MyBatis 中,当我们执行插入操作后,经常需要获取数据库生成的主键值(如自增ID、序列值等),MyBatis 提供了几种方式来实现主键返回功能,所以本文给大家介绍了MyBatis实现主键返回的全攻略,需要的朋友可以参考下

引言

在 MyBatis 中,当我们执行插入操作后,经常需要获取数据库生成的主键值(如自增ID、序列值等)。MyBatis 提供了几种方式来实现主键返回功能。

一、主要应用场景

  1. 插入数据后需要立即使用生成的主键
  2. 需要将主键值用于后续业务逻辑或关联操作
  3. 需要返回完整对象(包含主键)给前端

二、核心实现方式

1. 使用 useGeneratedKeys 和 keyProperty(推荐)

这是最常用的方式,适用于支持自动生成主键的数据库(如 MySQL、SQL Server)。

XML 配置方式

<insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO user (username, email, age)
    VALUES (#{username}, #{email}, #{age})
</insert>

注解配置方式

@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
@Insert("INSERT INTO user (username, email, age) VALUES (#{username}, #{email}, #{{age})")
int insertUser(User user);

2. 使用 <selectKey> 元素

这种方式更灵活,适用于所有数据库,特别是那些不支持自动生成主键的数据库(如 Oracle)。

MySQL 示例

<insert id="insertUser" parameterType="User">
    <selectKey keyProperty="id" resultType="java.lang.Long" order="AFTER">
        SELECT LAST_INSERT_ID()
    </selectKey>
    INSERT INTO user (username, email, age)
    VALUES (#{username}, #{email}, #{age})
</insert>

Oracle 示例

<insert id="insertUser" parameterType="User">
    <selectKey keyProperty="id" resultType="java.lang.Long" order="BEFORE">
        SELECT user_seq.NEXTVAL FROM DUAL
    </selectKey>
    INSERT INTO user (id, username, email, age)
    VALUES (#{id}, #{username}, #{email}, #{age})
</insert>

3. 注解方式使用 @SelectKey

@Insert("INSERT INTO user (username, email, age) VALUES (#{username}, #{email}, #{age})")
@SelectKey(statement = "SELECT LAST_INSERT_ID()", keyProperty = "id", 
           resultType = Long.class, before = false)
int insertUser(User user);

三、属性详解

1. useGeneratedKeys

  • 作用:告诉 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键
  • 取值:true|false
  • 默认值:false

2. keyProperty

  • 作用:指定能够唯一识别对象的属性(即主键字段)
  • 注意:如果是复合主键,可以用逗号分隔多个属性名

3. keyColumn

  • 作用:设置生成键值在表中的列名
  • 注意:某些数据库(如 PostgreSQL)必须指定,但大部分情况下 MyBatis 可以自动识别

4. <selectKey> 属性

  • keyProperty:指定主键字段对应的属性名
  • resultType:主键的类型
  • order:执行顺序,BEFORE|AFTER
    • BEFORE:先获取主键,再执行插入语句
    • AFTER:先执行插入语句,再获取主键

四、使用示例

实体类

public class User {
    private Long id;
    private String username;
    private String email;
    private Integer age;
    
    // 构造方法、getter、setter 省略
}

Mapper 接口

public interface UserMapper {
    int insertUser(User user);
    
    @Options(useGeneratedKeys = true, keyProperty = "id")
    @Insert("INSERT INTO user (username, email, age) VALUES (#{username}, #{email}, #{age})")
    int insertUserWithAnnotation(User user);
}

测试代码

// 获取 SqlSession 和 Mapper
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

// 创建用户对象
User user = new User();
user.setUsername("john_doe");
user.setEmail("john@example.com");
user.setAge(25);

// 执行插入操作
int result = userMapper.insertUser(user);

// 插入成功后,主键会自动回填到 user 对象中
System.out.println("插入成功,生成的主键ID: " + user.getId());

// 此时可以直接使用 user.getId() 进行后续操作

五、不同数据库的注意事项

MySQL

  • 使用 useGeneratedKeys="true"SELECT LAST_INSERT_ID()
  • 表必须具有自增主键

Oracle

  • 需要使用序列(Sequence)
  • 通常使用 order="BEFORE"

PostgreSQL

  • 使用 useGeneratedKeys="true"
  • 可能需要指定 keyColumn

SQL Server

  • 使用 useGeneratedKeys="true"
  • 也可以使用 SELECT SCOPE_IDENTITY()

六、最佳实践

  1. 推荐使用 useGeneratedKeys:代码更简洁,性能更好
  2. 明确指定 keyProperty:避免因属性名不一致导致的问题
  3. 考虑使用 keyColumn:当数据库列名与对象属性名不一致时特别有用
  4. 测试多种情况:特别是批量插入时的主键返回行为
  5. 处理复合主键:如果需要返回多个生成的值,可以用逗号分隔多个属性名
<!-- 复合主键示例 -->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id,version">
    INSERT INTO user (...) VALUES (...)
</insert>

七、常见问题解决

主键没有回填到对象中

  • 检查 keyProperty 是否与实体类的属性名一致
  • 检查数据库是否确实生成了主键

批量插入时主键返回

  • 某些数据库可能只返回最后一个插入的主键
  • 考虑使用 <foreach> 结合 <selectKey> 实现批量主键返回

通过合理使用 MyBatis 的主键返回功能,可以大大简化代码并提高开发效率。

到此这篇关于MyBatis实现主键返回功能的几种方式的文章就介绍到这了,更多相关MyBatis主键返回攻略内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 数据同步利器DataX简介及如何使用

    数据同步利器DataX简介及如何使用

    DataX 是阿里云 DataWorks数据集成 的开源版本,使用Java 语言编写,在阿里巴巴集团内被广泛使用的离线数据同步工具/平台,今天给大家分享一个阿里开源的数据同步工具DataX,在Github拥有14.8k的star,非常受欢迎
    2024-02-02
  • Java实现Excel图片URL筛选与大小检测的全过程

    Java实现Excel图片URL筛选与大小检测的全过程

    在数据处理场景中,我们常需筛选Excel中的图片URL,本文分享一个完整的Java方案,涵盖从读取图片URL到检测有效性、筛选大小,再到生成新Excel文件的全过程,同时讲解开发与优化过程,需要的朋友可以参考下
    2025-08-08
  • Struts2实现单文件或多文件上传功能

    Struts2实现单文件或多文件上传功能

    这篇文章主要为大家详细介绍了Struts2实现单文件或多文件上传功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03
  • 一篇文章带你玩转JAVA单链表

    一篇文章带你玩转JAVA单链表

    这篇文章主要为大家详细介绍了Java实现带头结点的单链表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • Java数据结构(线性表)详解

    Java数据结构(线性表)详解

    本文主要介绍了Java数据结构(线性表)的相关知识。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • SpringBoot集成Auth0 JWT的示例代码

    SpringBoot集成Auth0 JWT的示例代码

    本文主要介绍了SpringBoot集成Auth0 JWT的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • HttpClient实现远程调用

    HttpClient实现远程调用

    这篇文章主要为大家详细介绍了HttpClient实现远程调用的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • Java JVM字节码指令集总结整理与介绍

    Java JVM字节码指令集总结整理与介绍

    本节将会着重介绍一下JVM中的指令集、Java是如何跨平台的、JVM指令集参考手册等内容。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • Java中List的使用方法简单介绍

    Java中List的使用方法简单介绍

    这篇文章主要针对Java中List的使用方法为大家介绍了进行简单介绍,List是个集合接口,只要是集合类接口都会有个“迭代子”( Iterator ),利用这个迭代子,就可以对list内存的一组对象进行操作,感兴趣的小伙伴们可以参考一下
    2016-07-07
  • SpringBoot基于Mybatis拦截器和JSqlParser实现数据隔离

    SpringBoot基于Mybatis拦截器和JSqlParser实现数据隔离

    本文将介绍如何在 Spring Boot 项目中利用Mybatis的强大拦截器机制结合JSqlParser,一个功能丰富的 SQL 解析器,来轻松实现数据隔离的目标,本文根据示例展示如何根据当前的运行环境来实现数据隔离,需要的朋友可以参考下
    2024-04-04

最新评论