目录

添加记录后获取主键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. 聚类——GMM

    聚类——认识GMM算法 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 一.GMM概述 二.GMM算法步骤 三.具体推导参考文献 1. 李航. 统计学习 ...

  2. Scrapy案例01-爬取传智播客主页上的老师信息

    目录 1. 新建scrapy项目 2. 爬虫文件: 2.1. 查看需要爬取内容存在哪里: 2.2. 设置item需要保存的数据变量 2.3. 创建爬虫文件 2.4. 保存数据 2.5. yield的用 ...

  3. 我的第一个python web开发框架(35)——权限数据库结构设计

    接下来要做的是权限系统的数据库结构设计,在上一章我们了解了权限系统是通过什么来管理好权限的,我们选用其中比较常用的权限系统来实现当前项目管理要求. 下面是我们选择的权限系统关系模型: 从以上关系可以看 ...

  4. Springboot整合Ehcache缓存

    Pom.xml导包 <!-- ehcache --> <dependency> <groupId>org.springframework.boot</grou ...

  5. Java注解开发与应用案例

    Java注解开发与应用案例 Annotation(注解)是JDK5.0及以后版本引入的,可以对包.类.属性.方法的描述,给被述对象打上标签,被打上标签后的类.属性.方法将被赋予特殊的“功能”:打个比喻 ...

  6. i春秋 百度杯”CTF比赛 十月场 login

    出现敏感的信息,然后进行登录 登录成功发现奇怪的show 然后把show放到发包里面试一下 出现了源码,审计代码开始 出flag的条件要user 等于春秋 然后进行login来源于反序列化后的logi ...

  7. python 中内存释放与函数传递numpy数组问题

    numpy.array 作为参数传入函数中时,是作为引用进去的,函数内部对这个数组的修改会直接修改原始数据.在函数中需要暂时修改数据,不对原始数据造成影响的话,需要用 np.copy() 先拷贝一份, ...

  8. OpenStack-Storage(6)

    一. DAS/NAS/SAN 1.存储分类 (1)内置存储 (2)外挂存储 DAS (DirectAttached Storage):直连式存储 FAS (FabricAttached Storage ...

  9. 2 数据分析之Numpy模块(1)

    Numpy Numpy(Numerical Python的简称)是高性能科学计算和数据分析的基础包.它是我们课程所介绍的其他高级工具的构建基础. 其部分功能如下: ndarray, 一个具有复杂广播能 ...

  10. $router和$route的区别

    在路由跳转的时候除了用router-link标签以外需要在script标签在事件里面跳转,所以有个方法就是在script标签里面写this.$router.push('要跳转的路径名'), 在写的时候 ...