问题描述

添加记录后获取主键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元素构建批量添加语句。

实现原理

需要注意的是,不论在XML映射器还是在接口映射器中,添加记录的主键值并非添加操作的返回值。

实际上,在MyBatis中执行添加操作时只会返回当前添加的记录数。

package org.apache.ibatis.executor.statement;
public class PreparedStatementHandler extends BaseStatementHandler {@Overridepublic 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 insert操作的时序图:

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

参考文章

https://www.cnblogs.com/nuccch/p/9067305.html

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——insert并返回主键ID解决方案相关推荐

  1. MyBatis—insert语句返回主键和selectKey标签

    本文已同步至个人博客liaosi's blog - MyBatis-insert语句返回主键和selectKey标签 往数据库中插入一条记录后,有时候我们需要这条记录的主键,用于后续的操作.如果在插入 ...

  2. 使用mybatis plus添加返回主键id

    使用mybatis plus时返回的主键id,返回的数据是1515287203954688002的,这显然不是我想要的 orderDAO.insert(orderDO); return orderDO ...

  3. 160613、MyBatis insert操作返回主键

    在使用MyBatis做持久层时,insert语句默认是不返回记录的主键值,而是返回插入的记录条数:如果业务层需要得到记录的主键时,可以通过配置的方式来完成这个功能,针对Sequence主键而言,在执行 ...

  4. MyBatis insert操作返回主键

    在使用MyBatis做持久层时,insert语句默认是不返回记录的主键值,而是返回插入的记录条数:如果业务层需要得到记录的主键时,可以通过配置的方式来完成这个功能 针对Sequence主键而言,在执行 ...

  5. Mybatis批量插入,返回主键ID不成功,巨坑

    一.场景说明 批量插入,返回主键ID报错 org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibati ...

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

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

  7. 使用mybatis插入数据(insert)时返回主键的问题

    使用mybatis做插入操作时,想要获取新增记录的主键,我发现现在的方式和以前的方式有所区别,即以前是直接通过方法返回,现在是将主键设置在数据实体对象中. 下面对mybatis进行insert时返回主 ...

  8. mybatis 主键自增 insert后返回主键

    mybatis 主键自增 insert后返回主键 : <insert id="insertStudentAutoKey" parameterType="Studen ...

  9. Mybatis执行插入语句后并返回主键ID

    我们知道JDBC可以实现插入语句后返回主键Id,那mybatis可以实现吗?答案是肯定的. 1.MySQL数据库设置ID自增情况 <insert id="insertUser" ...

最新文章

  1. Spark:如何替换sc.parallelize(List(item1,item2)).collect().foreach(row={})为并行?
  2. Android 监听APP进入前台、后台
  3. 腾讯地图api修改信息窗口样式_DOTA2 地图编辑器指南(二):总览
  4. Kinect2.0-空间长度测量
  5. 同一条sql在mysql5.6和5.7版本遇到的问题。
  6. mysql------explain工具
  7. 关于Relay Log无法自动删除的问题
  8. poj 2356 Find a multiple dfs 爆搜!!!!
  9. 织梦安全的思路---未实践
  10. 张朝阳:走出焦虑,不再焦虑
  11. Fabric开发(三) Ubuntu20.04.1快速搭建Fabric1.4.3 (排雷版)
  12. 遥感影像的特征空间图
  13. CSS基础常识问答(四)
  14. 新建web.xml文件头报错报红xmlns=http://xmlns.jcp.org/xml/ns/javaee,http://xmlns.jcp.org/xml/ns/javaee/web-ap
  15. VC中常见的108个问题
  16. CentOS配置Jenkins+Android+fir+pyger(蒲公英)+qiniu(七牛)
  17. win10卸载WSL2记录
  18. PX4多传感器优先级判断
  19. 一个女程序员职场自述:彻骨的孤独
  20. WinGate 6.0 build 984铪铪铪

热门文章

  1. 程序员的.NET时代
  2. c# 睡眠3秒_C#中的闭包和意想不到的坑
  3. oracle xmltype使用,oracle的xmltype基本使用有哪些呢?
  4. java打包后发布找不到jsp_eclipse中web项目部署以后jsp的java文件找不到问题(Tomcat配置serverlocations)...
  5. html批量翻译 github,英文单词短语批量翻译工具WordListTranslator
  6. springboot 前缀_SpringBoot配置文件的注入
  7. 数据结构与算法(四):二叉树
  8. c语言中的数字菱形,打印数字菱形,急啊,帮帮小女子啊。。。
  9. 画出该lti系统的幅频特性响应曲线_一文带你通俗理解幅频响应和相频响应
  10. java jpa hibernate_java - JPA和Hibernate - Criteria与JPQL或HQL