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主键返回攻略内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java redisson实现分布式锁原理详解

    Java redisson实现分布式锁原理详解

    这篇文章主要介绍了Java redisson实现分布式锁原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • SpringMVC的REST风格的四种请求方式总结

    SpringMVC的REST风格的四种请求方式总结

    下面小编就为大家带来一篇SpringMVC的REST风格的四种请求方式总结。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • Java 断言 assert的用法详解

    Java 断言 assert的用法详解

    Java assert断言机制是Java5中推出的新特性,它主要用于在程序运行时检查状态或假设的正确性,本篇文章将全面详细地讲解Java assert断言机制,包括断言概述、语法规则、工作原理、使用场景、注意事项以及示例代码等方面,需要的朋友可以参考下
    2023-05-05
  • IntelliJ IDEA 代码运行时中文出现乱码问题及解决方法

    IntelliJ IDEA 代码运行时中文出现乱码问题及解决方法

    在我们刚接触到IDEA时,想美滋滋的敲一个“hello world”来问候这个世界,但难免会遇到这种问题乱码,这篇文章主要介绍了解决IntelliJ IDEA 代码运行时中文出现乱码问题,需要的朋友可以参考下
    2023-09-09
  • java编写创建数据库和表的程序

    java编写创建数据库和表的程序

    这篇文章主要为大家详细介绍了java编写创建数据库和表的程序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • 详解Java编程中final,finalize,finally的区别

    详解Java编程中final,finalize,finally的区别

    这篇文章主要介绍了详解Java编程中final,finalize,finally的区别,这个在Java面试题中简直是太常见了...需要的朋友可以参考下
    2015-11-11
  • SpringBoot的启动速度优化

    SpringBoot的启动速度优化

    随着我们项目的不断迭代 Bean 的数量会大大增加,如果都在启动时进行初始化会非常耗时,本文主要介绍了SpringBoot的启动速度优化,感兴趣的可以了解一下
    2023-09-09
  • mybatis 根据id批量删除的实现操作

    mybatis 根据id批量删除的实现操作

    这篇文章主要介绍了mybatis 根据id批量删除的实现操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • Springboot整合Shiro实现登录与权限校验详细解读

    Springboot整合Shiro实现登录与权限校验详细解读

    本文给大家介绍Springboot整合Shiro的基本使用,Apache Shiro是Java的一个安全框架,Shiro本身无法知道所持有令牌的用户是否合法,我们将整合Shiro实现登录与权限的验证
    2022-04-04
  • Spring Boot 4.0 牵手RabbitMQ注解魔法开启消息之旅

    Spring Boot 4.0 牵手RabbitMQ注解魔法开启消息之旅

    本文主要介绍了RabbitMQ与SpringBoot4.0的结合使用,探讨了如何在SpringBoot项目中集成RabbitMQ,并通过注解方式声明队列、交换机和绑定关系,感兴趣的朋友跟随小编一起看看吧
    2026-03-03

最新评论