目录

添加记录后获取主键ID,这是一个很常见的需求,特别是在一次前端调用中需要插入多个表的场景。

除了添加单条记录时获取主键值,有时候可能需要获取批量添加记录时各记录的主键值,MyBatis从3.3.1版本开始支持批量添加记录并返回各记录主键字段值。

添加单一记录时返回主键ID

添加一条记录时返回主键值,在xml映射器和接口映射器中都可以实现。

在映射器中配置获取记录主键值

  • xml映射器

在定义xml映射器时设置属性useGeneratedKeys值为true,并分别指定属性keyProperty和keyColumn为对应的数据库记录主键字段与Java对象的主键属性。

<mapper namespace="org.chench.test.mybatis.mapper">
<!-- 插入数据:返回记录主键id值 -->
<insert id="insertOneTest" parameterType="org.chench.test.mybatis.model.Test" useGeneratedKeys="true" keyProperty="id" keyColumn="id" >
insert into test(name,descr,url,create_time,update_time)
values(#{name},#{descr},#{url},now(),now())
</insert>
</mapper>
  • 接口映射器

在接口映射器中通过注解@Options分别设置参数useGeneratedKeys,keyProperty,keyColumn值

// 返回主键字段id值
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
@Insert("insert into test(name,descr,url,create_time,update_time) values(#{name},#{descr},#{url},now(),now())")
Integer insertOneTest(Test test);

获取新添加记录主键字段值

需要注意的是,在MyBatis中添加操作返回的是记录数并非记录主键id。因此,如果需要获取新添加记录的主键值,需要在执行添加操作之后,直接读取Java对象的主键属性。

Integer rows = sqlSession.getMapper(TestMapper.class).insertOneTest(test);
System.out.println("rows = " + rows); // 添加操作返回记录数
System.out.println("id = " + test.getId()); // 执行添加操作之后通过Java对象获取主键属性值

添加批量记录时返回主键ID

如果希望执行批量添加并返回各记录主键字段值,只能在xml映射器中实现,在接口映射器中无法做到。

<!-- 批量添加数据,并返回主键字段 -->
<insert id="insertBatchTest" useGeneratedKeys="true" keyProperty="id">
INSERT INTO test(name,descr,url,create_time,update_time) VALUES
<foreach collection="list" separator="," item="t">
(#{t.name},#{t.descr},#{t.url},now(),now())
</foreach>
</insert>

可以看到,执行批量添加并返回记录主键值的xml映射器配置,跟添加单条记录时是一致的。不同的地方仅仅是使用了foreach元素构建批量添加语句。

获取主键ID实现原理

需要注意的是,不论在xml映射器还是在接口映射器中,添加记录的主键值并非添加操作的返回值。实际上,在MyBatis中执行添加操作时只会返回当前添加的记录数。

package org.apache.ibatis.executor.statement;
public class PreparedStatementHandler extends BaseStatementHandler {
@Override
public int update(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
// 真正执行添加操作的SQL语句
ps.execute();
int rows = ps.getUpdateCount();
Object parameterObject = boundSql.getParameterObject();
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
// 在执行添加操作完毕之后,再处理记录主键字段值
keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
// 添加记录时返回的是记录数,而并非记录的主键字段值
return rows;
}
}

顺便看一下MyBatis添加操作的时序图:

跟踪时序图执行步骤可以看到,MyBatis最终是通过MySQL驱动程序获取到了新添加的记录主键值。

【参考】

https://github.com/mybatis/mybatis-3/pull/350 Support insert multiple rows and write-back id.More about insert multipl...

https://www.zhihu.com/question/21153827 mybatis 批量插入如何返回每个条记录的自生成主键?

https://blog.csdn.net/jiangeeq/article/details/55047116 Mybatis批量插入返回插入成功后的主键id

https://blog.csdn.net/top_code/article/details/52404345 MyBatis 3.3.1 批量插入多行回写自增id

深入浅出mybatis之返回主键ID的更多相关文章

  1. Mybatis添加返回主键ID

    1.对应xml文件<insert id="insert" parameterType="DetectStandard"useGeneratedKeys=& ...

  2. Mybatis insert返回主键ID

    Mybatis insert语句书写 <insert id="insertSelective" useGeneratedKeys="true" keyPr ...

  3. Mybatis Insert 返回主键ID

    <insert id="insert" useGeneratedKeys="true" keyProperty="u_Id" para ...

  4. mybatis添加记录时返回主键id

    参考:mybatis添加记录时返回主键id 场景 有些时候我们在添加记录成功后希望能直接获取到该记录的主键id值,而不需要再执行一次查询操作.在使用mybatis作为ORM组件时,可以很方便地达到这个 ...

  5. mybatis 批量插入 返回主键id

    我们都知道Mybatis在插入单条数据的时候有两种方式返回自增主键: 1.对于支持生成自增主键的数据库:增加 useGenerateKeys和keyProperty ,<insert>标签 ...

  6. MyBatis插入记录时返回主键id的方法

    有时候插入记录之后需要使用到插入记录的主键,通常是再查询一次来获取主键,但是MyBatis插入记录时可以设置成返回主键id,简化操作,方法大致有两种. 对应实体类: public class User ...

  7. 开启事务时mybatis返回主键id

    先说一下没有注解的 先给出实体类: public class City { private int city_id; private String city_name; public int getC ...

  8. MyBatis insert返回主键(sqlserver2008)

    mybatis insert返回主键(sqlserver2008)   MyBatisXML配置,下面两种方式都行 方式1: <insert id="insert" para ...

  9. Oracle 在函数或存储过程中执行一条插入语句并返回主键ID值

    有时,我们需要往一张表插入一条记录,同时返回主键ID值. 假定主键ID的值都是通过对应表的SEQUENCE来获得,然后进行ID赋值 这里有几种情况需要注意: 1)如果建表语句含有主键ID的触发器,通过 ...

随机推荐

  1. SAP CRM Installed Bases(IBase)简介

    SAP CRM使用Installed Base(以下简称IBase)来组织服务相关对象并进行管理.因为我在最近的工作中经常接触这个概念,所以学习了一点相关文档.下面是文档的翻译. 本文链接:https ...

  2. HBase Client JAVA API

    旧 的 HBase 接口逻辑与传统 JDBC 方式很不相同,新的接口与传统 JDBC 的逻辑更加相像,具有更加清晰的 Connection 管理方式. 同时,在旧的接口中,客户端何时将 Put 写到服 ...

  3. web框架开发-Django模型层(1)之ORM简介和单表操作

    ORM简介 不需要使用pymysql的硬编码方式,在py文件中写sql语句,提供更简便,更上层的接口,数据迁移方便(有转换的引擎,方便迁移到不同的数据库平台)…(很多优点),缺点,因为多了转换环节,效 ...

  4. Django-CRM项目学习(三)-stark的页面展示

    开始今日份整理,主要为stark组件的增删改以及model_form组件的使用以及form组件的回顾 1.list_display_link功能 功能:客制化字段进行跳转到指定的页面(编辑页面) 1. ...

  5. android glide图片加载框架

    项目地址: https://github.com/bumptech/glide Glide作为安卓开发常用的图片加载库,有许多实用而且强大的功能,那么,今天就来总结一番,这次把比较常见的都写出来,但并 ...

  6. leetcode 169. Majority Element 、229. Majority Element II

    169. Majority Element 求超过数组个数一半的数 可以使用hash解决,时间复杂度为O(n),但空间复杂度也为O(n) class Solution { public: int ma ...

  7. SkylineGlobe7.0.1版本 通过鼠标左右平移模型对象

    帮同事写了一段测试代码,如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "ht ...

  8. Oracle的表被锁后的恢复

    运行下列SQL,找出数据库的serial#,执行结果如下图所示 SELECT T2.USERNAME, T2.SID, T2.SERIAL#, T2.LOGON_TIME   FROM V$LOCKE ...

  9. Flask上下文管理源码分析 ——(3)

    引出的问题 Flask如何使用上下文临时把某些对象变为全局可访问 首先我们做如下的几种情况的假设 情况一:单进程单线程 这种情况可以基于全局变量存储临时的对象 情况二:单进程多线程 这种情况会出现多个 ...

  10. Vue之状态管理(vuex)与接口调用

    Vue之状态管理(vuex)与接口调用 一,介绍与需求 1.1,介绍 1,状态管理(vuex) Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态 ...