【MyBatis】如何在数据插入后获取对应的主键 ID

在数据库操作中,我们经常需要在插入数据后立即获取生成的主键 ID。这种需求在需要维护关联表数据或进行后续业务处理时尤为常见。本文将深入探讨 MyBatis 中获取插入主键的多种实现方式,并解析其底层原理及性能影响。

一、单条数据插入获取 ID

1. useGeneratedKeys 方式(推荐)
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO user(name, age) 
    VALUES(#{name}, #{age})
insert>
  • 原理:通过 JDBC 的 Statement.getGeneratedKeys() 方法获取数据库生成的主键
  • 优势:无需额外 SQL 查询
  • 要求:数据库必须支持自增主键(如 MySQL/AUTO_INCREMENT、PostgreSQL/SERIAL)

useGeneratedKeyskeyProperty 是 MyBatis 中用于处理自动生成键(例如自增主键)的两个重要属性。它们主要用于插入操作,以便在插入新记录后获取数据库生成的键值。

useGeneratedKeys 属性
  • 用途useGeneratedKeys 属性用于指示 MyBatis 是否应使用 JDBC 的 getGeneratedKeys 方法来获取数据库生成的键值。
  • 适用场景:通常用于插入操作中,当你希望在插入记录后自动获取数据库生成的键(如自增 ID)。
  • 工作原理
    • useGeneratedKeys 设置为 true 时,MyBatis 会在执行插入操作后调用 JDBC 的 getGeneratedKeys 方法。
    • 这个方法会返回数据库生成的键值(例如,自增的主键 ID)。
    • 这要求数据库和 JDBC 驱动程序支持 getGeneratedKeys 方法。
keyProperty 属性
  • 用途keyProperty 指定了 MyBatis 应该将生成的键值赋给哪个 Java 对象的属性。
  • 工作原理
    • keyProperty 的值应该是你的 Java 对象中用于存储生成键的属性名。
    • 当 MyBatis 获取到生成的键后,它会将键值赋给这个指定的属性。
2. selectKey 方式(通用方案)
<insert id="insertUser">
    <selectKey keyProperty="id" resultType="long" order="AFTER">
        SELECT LAST_INSERT_ID()
    selectKey>
    INSERT INTO user(name, age)
    VALUES(#{name}, #{age})
insert>
  • 适用场景
    • 使用数据库序列(如 Oracle)
    • 需要自定义主键生成规则
  • 注意order 属性需设置为 AFTER(插入后执行)

二、批量插入获取 ID

<insert id="batchInsert" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO user(name, age) VALUES
    <foreach collection="list" item="item" separator=",">
        (#{item.name}, #{item.age})
    foreach>
insert>
  • 执行后效果
    List<User> users = new ArrayList<>();
    // 添加多个 user 对象
    mapper.batchInsert(users);
    // 每个 user 对象的 id 会被自动赋值
    

三、底层实现原理

1. JDBC 驱动层
  • Statement.RETURN_GENERATED_KEYS 标志位通知数据库返回生成键
  • 不同数据库驱动实现差异:
    • MySQL:通过 SELECT LAST_INSERT_ID() 实现
    • PostgreSQL:使用 RETURNING 子句
    • Oracle:依赖序列和 RETURNING INTO 子句

JDBC获取 ID 使用示例

package com.gumei.core.dao.mysql.basic;  
  
import org.junit.jupiter.api.Test;  
  
import java.sql.*;  
  
public class JDBCTest {  
  
  
    @Test  
    public void generatedKeysTest(){  
        String url = "jdbc:mysql://localhost:3306/mysql?characterEncoding=UTF-8&useSSL=false";  
        String user = "root";  
        String password = "mysql123456";  
  
        String insertSQL = "INSERT INTO demo_table (name, age) VALUES (?, ?)";  
  
        try (Connection conn = DriverManager.getConnection(url, user, password);  
             PreparedStatement prepatedStatement = conn.prepareStatement(insertSQL, Statement.RETURN_GENERATED_KEYS)) {  
            // 设置参数  
            prepatedStatement.setString(1, "John Doe");  
            prepatedStatement.setString(2, "17");  
  
            // 执行插入  
            int affectedRows = prepatedStatement.executeUpdate();  
  
            // 检查插入是否成功  
            if (affectedRows > 0) {  
                // 获取生成的键  
                try (ResultSet generatedKeys = prepatedStatement.getGeneratedKeys()) {  
                    if (generatedKeys.next()) {  
                        long id = generatedKeys.getLong(1);  
                        System.out.println("Inserted record ID: " + id);  
                    }  
                }  
            } else {  
                System.out.println("No rows affected.");  
            }  
  
        } catch (SQLException e) {  
            e.printStackTrace();  
        }  
    }  
  
}
2. MyBatis 处理流程

【MyBatis】如何在数据插入后获取对应的主键 ID_第1张图片

以上,祝你今天愉快!

你可能感兴趣的:(Java实战,MyBatis,mybatis,java,数据库)