Mybatis(二):插入操作返回主键

本文介绍使用MyBatis插入数据并返回主键的两种方法:使用useGeneratedKeys+keyProperty和selectKey。通过示例代码展示了如何在实际项目中应用这两种方法。

插入数据并返回主键这种需求很常见,所以列出来。

一、实现方式
1. 使用useGeneratedKeys+keyProperty (推荐)

简单来说就是配置:

<insert id="" useGeneratedKeys="true" keyProperty="id">

将插入的ID赋值给设置的keyProperty对象属性字段里面,一般也就是对象的ID,比如插入User对象,设置赋值主键ID给id字段。

2. 使用selectKey

MySQL 数据库可以使用如下方式。

<selectKey keyProperty="id" resultType="int" order="AFTER">
    SELECT LAST_INSERT_ID()
</selectKey>
二、具体演示:

基于上篇文章的代码新增:

package cn.saytime.mapper;

import cn.saytime.domain.User;
import java.util.List;

/**
 * @author L
 * @ClassName cn.saytime.mapper.UserMapper
 * @Description
 */
public interface UserMapper {

    /**
     * 保存用户,返回主键,形式1
     * @param user
     */
    int saveReturnPK1(User user);

    /**
     * 保存用户,返回主键,形式2
     * @param user
     */
    int saveReturnPK2(User user);

}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.saytime.mapper.UserMapper" >

    <!-- 增,返回主键 形式1 -->
    <insert id="saveReturnPK1" parameterType="cn.saytime.domain.User" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO `test`.`tb_user`(`username`, age) VALUES(#{username}, #{age})
    </insert>

    <!-- 增,返回主键 形式2 -->
    <insert id="saveReturnPK2" parameterType="cn.saytime.domain.User">
        <selectKey keyProperty="id" resultType="int" order="AFTER">
            SELECT LAST_INSERT_ID()
        </selectKey>
        INSERT INTO `test`.`tb_user`(`username`, age) VALUES(#{username}, #{age})
    </insert>

</mapper>

测试:

import cn.saytime.domain.User;
import cn.saytime.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by L on 2018/1/3.
 */
public class TestUserMapper {

    SqlSessionFactory sqlSessionFactory = null;
    SqlSession sqlSession = null;
    UserMapper userMapper = null;

    @Before
    public void before(){
        // mybatis 配置文件地址
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 加载配置文件,并构建sqlSessionFactory
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        // 获取sqlSession对象
        sqlSession = sqlSessionFactory.openSession();
        userMapper = sqlSession.getMapper(UserMapper.class);
    }

    @After
    public void after(){
        if(sqlSession != null){
            // 注意这里的commit,否则提交不成功
            sqlSession.commit();
            sqlSession.close();
        }
    }

    /**
     * 测试保存用户返回主键,注意返回的主键塞到了插入对象user的id中
     */
    @org.junit.Test
    public void testSaveReturnPK(){
        // 形式1
        User user1 = new User();
        user1.setUsername("李四");
        user1.setAge(18);
        int c1 = userMapper.saveReturnPK1(user1);
        System.out.println("新增用户李四,返回主键:" + user1.getId() + "  操作数量:" + c1);

        // 形式2
        User user2 = new User();
        user2.setUsername("王五");
        user2.setAge(19);
        int c2 = userMapper.saveReturnPK1(user2);
        System.out.println("新增用户王五,返回主键:" + user2.getId() + "  操作数量:" + c2);
    }

}
新增用户李四,返回主键:3  操作数量:1
新增用户王五,返回主键:4  操作数量:1

再次注意这里UserMapper.saveResultPK返回之后的数字仍然是操作数量,主键在User对象里面的id。

<think>我们正在查找在MyBatis的XML映射文件中插入数据时返回主键的方法。根据引用内容,有两种主要方法: 1. 使用`useGeneratedKeys`属性(适用于支持自动生成主键的数据库,如MySQL) 2. 使用`selectKey`子元素(适用于各种数据库,尤其是Oracle等使用序列的数据库) 下面分别详细说明这两种方法: 方法一:使用`useGeneratedKeys`属性(推荐用于MySQL等自增主键) - 在`<insert>`标签中添加三个属性: useGeneratedKeys="true" // 表示使用数据库自动生成的主键 keyProperty="id" // 表示将生成的主键值设置到参数对象的哪个属性上(这里假设属性名为id) keyColumn="id" // (可选)指定数据库表的主键列名,如果属性名和列名一致可省略 - 示例代码(参考引用[1][5]): ```xml <insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id" keyColumn="id"> INSERT INTO user(name, email) VALUES (#{name}, #{email}) </insert> ``` - 执行插入后,传入的User对象的id属性会被自动赋值(即新生成的主键值)。 - 注意:此方法仅适用于支持自动生成主键的数据库(如MySQL、SQL Server等),并且主键列必须是自增的。 方法:使用`<selectKey>`子元素(通用方法,尤其适用于Oracle序列) - 在`<insert>`标签内部,添加一个`<selectKey>`子标签,用于在插入语句执行前后获取主键值。 - `<selectKey>`标签的属性: keyProperty:指定将结果设置到参数对象的哪个属性上(如id) resultType:主键的数据类型(如int, long等) order:指定执行顺序,AFTER表示在插入语句之后执行(适用于自增主键),BEFORE表示在插入语句之前执行(适用于序列,如Oracle) databaseId:可选,指定数据库厂商(用于多数据库支持) - 示例1(MySQL,使用LAST_INSERT_ID(),在插入之后获取)参考引用[2][4]: ```xml <insert id="insertUser" parameterType="User"> INSERT INTO user(name, email) VALUES (#{name}, #{email}) <selectKey keyProperty="id" resultType="long" order="AFTER"> SELECT LAST_INSERT_ID() </selectKey> </insert> ``` - 示例2(Oracle,使用序列,在插入之前获取): ```xml <insert id="insertUser" parameterType="User"> <selectKey keyProperty="id" resultType="long" order="BEFORE"> SELECT SEQ_USER.NEXTVAL FROM DUAL </selectKey> INSERT INTO user(id, name, email) VALUES (#{id}, #{name}, #{email}) </insert> ``` - 注意:对于Oracle,由于需要先获取序列值再插入,所以order为BEFORE,并且在插入语句中需要显式插入id列。 批量插入返回主键(参考引用[3]): - 对于批量插入MyBatis 3.3.1及以上版本支持返回主键。在`<insert>`标签中同样使用`useGeneratedKeys`和`keyProperty`,但keyProperty的值需要指定为集合中每个元素的主键属性。 - 示例: ```xml <insert id="insertBatch" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="id"> INSERT INTO user(name, email) VALUES <foreach collection="list" item="item" separator=","> (#{item.name}, #{item.email}) </foreach> </insert> ``` - 执行后,传入的List中的每个User对象的id属性都会被赋值。 总结: - MySQL等自增数据库:推荐使用`useGeneratedKeys`(更简洁)。 - Oracle等使用序列的数据库:使用`<selectKey>`并设置order="BEFORE"。 - 批量插入:同样使用`useGeneratedKeys`,并确保MyBatis版本>=3.3.1。 注意事项: - 确保传入的参数对象有对应的主键属性(如id)以及setter方法。 - 在调用插入方法后,可以直接从参数对象中获取主键值。 引用标识说明: - 使用`useGeneratedKeys`方法参考引用[1][3][5]。 - 使用`selectKey`方法参考引用[2][4]。 请根据实际使用的数据库类型选择合适的方法。 </think>### MyBatis XML 插入数据返回主键的两种核心方法 在 MyBatis XML 映射文件中,可通过以下两种方式实现插入数据后返回主键: --- #### 方法一:`useGeneratedKeys`属性(推荐用于自增主键数据库) **适用场景**:MySQL、SQL Server 等支持自动生成主键的数据库。 **实现步骤**: 1. 在 `<insert>` 标签中添加属性: ```xml <insert id="insertUser" parameterType="User" useGeneratedKeys="true" <!-- 启用自动生成主键 --> keyProperty="id" <!-- 主键映射到Java对象的属性名 --> keyColumn="id"> <!-- 数据库主键列名(可选) --> INSERT INTO user(name, email) VALUES (#{name}, #{email}) </insert> ``` 2. **调用后获取主键**: ```java User user = new User(); user.setName("Tom"); user.setEmail("tom@example.com"); userMapper.insertUser(user); // 执行插入 System.out.println("主键ID: " + user.getId()); // 直接获取主键 ``` **优势**: - 简洁高效,无需额外 SQL 语句[^1][^5] - 支持批量插入(需 MyBatis 3.3.1+)[^3] --- #### 方法:`<selectKey>`子标签(通用所有数据库) **适用场景**:Oracle 等使用序列生成主键的数据库,或需更灵活控制的场景。 **实现步骤**: ```xml <insert id="insertUser" parameterType="User"> INSERT INTO user(name, email) VALUES (#{name}, #{email}) <!-- 插入后查询主键 --> <selectKey keyProperty="id" <!-- 映射到Java对象的属性 --> resultType="Long" <!-- 主键数据类型 --> order="AFTER"> <!-- AFTER: 插入后执行 --> SELECT LAST_INSERT_ID() <!-- MySQL函数 --> </selectKey> </insert> ``` **关键参数说明**: - `keyProperty`:主键对应的 Java 对象属性名(如 `id`) - `resultType`:主键数据类型(如 `java.lang.Long`) - `order`: - `AFTER`:插入获取主键(适合自增主键) - `BEFORE`:插入获取主键(适合序列主键,如 Oracle)[^2][^4] - 自定义查询语句需适配数据库: - Oracle 示例:`SELECT sequence_name.NEXTVAL FROM DUAL` --- #### 两种方法对比 | **特性** | `useGeneratedKeys` | `<selectKey>` | |------------------|----------------------------------------|-----------------------------------| | 适用数据库 | MySQL/SQL Server 等自增主键 | 所有数据库(包括Oracle) | | 配置复杂度 | ⭐ 简单(只需属性配置) | ⭐⭐⭐ 需写子标签和SQL | | 批量插入支持 | ✅ 支持 | ❌ 不支持 | | 事务安全性 | ✅ 可靠 | ✅ 可靠 | | 灵活性 | 基础功能 | 可自定义复杂逻辑(如联合主键) | --- #### 注意事项 1. **属性映射**:确保 `keyProperty` 与 Java 对象属性名严格匹配。 2. **批量插入**: - 使用 `useGeneratedKeys` 时,传入 `List<User>` 参数,每个元素自动获取主键[^3]。 - XML 需声明 `parameterType="java.util.List"`。 3. **Oracle 适配**: ```xml <selectKey keyProperty="id" resultType="Long" order="BEFORE"> SELECT SEQ_USER.NEXTVAL FROM DUAL <!-- 插入获取序列 --> </selectKey> ``` 4. **错误排查**: - 主键未赋值 → 检查 `keyProperty` 拼写和对象 setter 方法。 - 返回 null → 确认数据库是否支持自动主键(如 Oracle 需序列)。 通过以上方法,可灵活适配不同数据库,高效获取插入数据的主键值。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值