深入浅出mybatis之返回主键ID

目录
添加记录后获取主键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的更多相关文章
- Mybatis添加返回主键ID
1.对应xml文件<insert id="insert" parameterType="DetectStandard"useGeneratedKeys=& ...
- Mybatis insert返回主键ID
Mybatis insert语句书写 <insert id="insertSelective" useGeneratedKeys="true" keyPr ...
- Mybatis Insert 返回主键ID
<insert id="insert" useGeneratedKeys="true" keyProperty="u_Id" para ...
- mybatis添加记录时返回主键id
参考:mybatis添加记录时返回主键id 场景 有些时候我们在添加记录成功后希望能直接获取到该记录的主键id值,而不需要再执行一次查询操作.在使用mybatis作为ORM组件时,可以很方便地达到这个 ...
- mybatis 批量插入 返回主键id
我们都知道Mybatis在插入单条数据的时候有两种方式返回自增主键: 1.对于支持生成自增主键的数据库:增加 useGenerateKeys和keyProperty ,<insert>标签 ...
- MyBatis插入记录时返回主键id的方法
有时候插入记录之后需要使用到插入记录的主键,通常是再查询一次来获取主键,但是MyBatis插入记录时可以设置成返回主键id,简化操作,方法大致有两种. 对应实体类: public class User ...
- 开启事务时mybatis返回主键id
先说一下没有注解的 先给出实体类: public class City { private int city_id; private String city_name; public int getC ...
- MyBatis insert返回主键(sqlserver2008)
mybatis insert返回主键(sqlserver2008) MyBatisXML配置,下面两种方式都行 方式1: <insert id="insert" para ...
- Oracle 在函数或存储过程中执行一条插入语句并返回主键ID值
有时,我们需要往一张表插入一条记录,同时返回主键ID值. 假定主键ID的值都是通过对应表的SEQUENCE来获得,然后进行ID赋值 这里有几种情况需要注意: 1)如果建表语句含有主键ID的触发器,通过 ...
随机推荐
- SAP CRM Installed Bases(IBase)简介
SAP CRM使用Installed Base(以下简称IBase)来组织服务相关对象并进行管理.因为我在最近的工作中经常接触这个概念,所以学习了一点相关文档.下面是文档的翻译. 本文链接:https ...
- HBase Client JAVA API
旧 的 HBase 接口逻辑与传统 JDBC 方式很不相同,新的接口与传统 JDBC 的逻辑更加相像,具有更加清晰的 Connection 管理方式. 同时,在旧的接口中,客户端何时将 Put 写到服 ...
- web框架开发-Django模型层(1)之ORM简介和单表操作
ORM简介 不需要使用pymysql的硬编码方式,在py文件中写sql语句,提供更简便,更上层的接口,数据迁移方便(有转换的引擎,方便迁移到不同的数据库平台)…(很多优点),缺点,因为多了转换环节,效 ...
- Django-CRM项目学习(三)-stark的页面展示
开始今日份整理,主要为stark组件的增删改以及model_form组件的使用以及form组件的回顾 1.list_display_link功能 功能:客制化字段进行跳转到指定的页面(编辑页面) 1. ...
- android glide图片加载框架
项目地址: https://github.com/bumptech/glide Glide作为安卓开发常用的图片加载库,有许多实用而且强大的功能,那么,今天就来总结一番,这次把比较常见的都写出来,但并 ...
- leetcode 169. Majority Element 、229. Majority Element II
169. Majority Element 求超过数组个数一半的数 可以使用hash解决,时间复杂度为O(n),但空间复杂度也为O(n) class Solution { public: int ma ...
- SkylineGlobe7.0.1版本 通过鼠标左右平移模型对象
帮同事写了一段测试代码,如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "ht ...
- Oracle的表被锁后的恢复
运行下列SQL,找出数据库的serial#,执行结果如下图所示 SELECT T2.USERNAME, T2.SID, T2.SERIAL#, T2.LOGON_TIME FROM V$LOCKE ...
- Flask上下文管理源码分析 ——(3)
引出的问题 Flask如何使用上下文临时把某些对象变为全局可访问 首先我们做如下的几种情况的假设 情况一:单进程单线程 这种情况可以基于全局变量存储临时的对象 情况二:单进程多线程 这种情况会出现多个 ...
- Vue之状态管理(vuex)与接口调用
Vue之状态管理(vuex)与接口调用 一,介绍与需求 1.1,介绍 1,状态管理(vuex) Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态 ...