目录

添加记录后获取主键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. 黑洞有毛 or 黑洞无毛:4星|《环球科学》2019年03月号

    <环球科学>2019年03月号 高水平的科普杂志.本期我感兴趣的话题有: 1:65岁以上老年人是转发假新闻的主力: 2:人的面孔特征可以通过50个维度来定义: 3:华裔科学家发现人脑颞叶中 ...

  2. C语言----int (*p)[4] ---思考总结

    a+1  跳4个int (*a)+1 跳一个int

  3. Django REST framework 中文文档

    Django REST framework介绍 现在前后端分离的架构设计越来越流行,业界甚至出现了API优先的趋势. 显然API开发已经成为后端程序员的必备技能了,那作为Python程序员特别是把Dj ...

  4. day23--面向对象之封装、继承、多态

    面向对象的三大特性: 封装: 在类的内部(class内部)可以由属性和方法,外部代码可以通过直接调用实例变量的方法来操作数据,这样就隐藏了内部的逻辑,但是外部还是可以直接修改实例的属性,因此当需求中存 ...

  5. Luogu5176 公约数 莫比乌斯反演、线性筛

    传送门 好像是我们联考时候的题目? 一个结论:\(\gcd(ij,ik,jk) \times \gcd(i,j,k) = \gcd(i,j) \times \gcd(i,k) \times \gcd( ...

  6. 09-JavaScript之伪数组arguments

    JavaScript之伪数组arguments arguments代表的是实参.有个讲究的地方是:arguments只在函数中使用. 1.返回函数实参的个数 使用argument.length方法返回 ...

  7. pyspider煎蛋无聊图爬取

    命令行pyspider,启动pyspider. web预览界面太小,解决方法:找到pyspider的安装路径下的debug.min.css,修改css代码: 将其中的iframe{border-wid ...

  8. MySQL CONCAT opposite

    csv - What is the opposite of GROUP_CONCAT in MySQL? - Stack Overflowhttps://stackoverflow.com/quest ...

  9. Powershell 函数中的CmdletBinding()是怎么回事?

    参考文章: Don Jones https://technet.microsoft.com/en-us/library/ff677563.aspx powershell 帮助文档: help abou ...

  10. 第七章· Redis Cluster 核心技术

    Redis Cluster 分布式集群 Redis Cluster 安装部署 Redis Cluster 集群管理操作(核心)