使用mybatis注解@Options实现添加记录时返回主键值

官网:http://www.mybatis.org/mybatis-3/index.html
在使用mybatis作为ORM框架时,我通常更喜欢使用注解而非xml配置文件的方式。
业务场景:添加记录之后需要返回自己自增长的主键字段值。
通常,我们会将DAO层写成如下代码(以添加员工Staff为例):
public interface StaffDAO {
@InsertProvider(type=StaffProvider.class, method="buildSinleStaff")
@Options(useGeneratedKeys=true, keyProperty="staff_id", keyColumn="staff_id")
public int addStaff(Staff staff);
}
显然,希望在执行addStaff()后返回新添加的员工记录的主键字段值,在这里为staff_id(staff_id为主键字段,且为自增类型)。
但是!!!经过多次验证,依然发现,返回值始终为:1!
跟踪mybatis源码发现,返回值其实是添加的记录数,而不是新加记录的主键字段值,所以永远为1。
mybatis添加记录时序图:
查看org.apache.ibatis.executor.statement.PreparedStatementHandler源码实现:
@Override
public int update(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
int rows = ps.getUpdateCount();
Object parameterObject = boundSql.getParameterObject();
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
return rows;
}
显然,返回值是受影响的记录数量,即:添加的记录数。
那么如何才能取得新添加记录的主键字段值呢?继续跟踪源码(org.apache.ibatis.executor.statement.PreparedStatementHandler):
@Override
public int update(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
int rows = ps.getUpdateCount();
Object parameterObject = boundSql.getParameterObject();
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
return rows;
}
显然,在执行插入记录操作之后,还执行了如下操作:
Object parameterObject = boundSql.getParameterObject(); KeyGenerator keyGenerator = mappedStatement.getKeyGenerator(); keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
在org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator中实现对主键字段的处理:
private void populateKeys(ResultSet rs, MetaObject metaParam, String[] keyProperties, TypeHandler<?>[] typeHandlers) throws SQLException {
for (int i = 0; i < keyProperties.length; i++) {
TypeHandler<?> th = typeHandlers[i];
if (th != null) {
Object value = th.getResult(rs, i + 1);
metaParam.setValue(keyProperties[i], value);
}
}
}
恍然大悟!
在使用mybatis注解@Options(useGeneratedKeys=true)获取新添加记录的自增长主键字段值时,需要在执行添加操作之后,直接访问对象的主键字段属性即可取得对应值。
回归到业务代码:
staffService.addStaff(staff); long staffId = staff.getStaff_id(); // 执行添加操作之后获取对象主键字段值
最后需要说明:在mybatis中使用注解实现添加记录时,可以使用@Insert或者@InsertProvider 2个注解,都可以使用@Options注解获取新添加记录的自增长主键字段值。
【参考】
http://isilic.iteye.com/blog/1810782 Mybatis使用:Sql Annotation
使用mybatis注解@Options实现添加记录时返回主键值的更多相关文章
- mybatis添加记录时返回主键id
参考:mybatis添加记录时返回主键id 场景 有些时候我们在添加记录成功后希望能直接获取到该记录的主键id值,而不需要再执行一次查询操作.在使用mybatis作为ORM组件时,可以很方便地达到这个 ...
- MyBatis插入记录时返回主键id的方法
有时候插入记录之后需要使用到插入记录的主键,通常是再查询一次来获取主键,但是MyBatis插入记录时可以设置成返回主键id,简化操作,方法大致有两种. 对应实体类: public class User ...
- mybatis添加数据时返回主键 insert 返回主键值
insert 返回主键值 useGeneratedKeys=“true” parameterType=“USer” keyProperty=“id”, <insert id="inse ...
- mybatis 08: 返回主键值的insert操作 + 利用UUID获取字符串(了解)
返回主键值的insert操作 应用背景 图示说明 在上述业务背景下,涉及两张数据表的关联操作:用户表 + 用户积分表 传统操作:在对用户表执行完插入语句后,再次查询该用户的uid,将该uid作为外键, ...
- MyBatis在Oracle中插入数据并返回主键的问题解决
引言: 在MyBatis中,希望在Oracle中插入数据之时,同一时候返回主键值,而非插入的条数... 环境:MyBatis 3.2 , Oracle. Spring 3.2 SQL Snipp ...
- [oracle] 如何使用myBatis在数据库中插入数据并返回主键
在MyBatis中,希望在Oracle中插入数据的同时返回主键值,而非插入的条数. ① oracle使用 selectKey. U_USER_INFO_SEQ 是在数据库中定义好的这张表关联的序列se ...
- MyBatis在insert插入操作时返回主键ID的配置
在使用MyBatis做持久层时,insert语句默认是不返回记录的主键值,而是返回插入的记录条数:如果业务层需要得到记录的主键时,可以通过Mapper.XML配置的方式来完成这个功能. 在 INSER ...
- mybatis 插入数据时返回主键
在使用MyBatis做持久层时,insert语句默认是不返回记录的主键值,而是返回插入的记录条数:显然,假如主键是你生成后插入的,自然你已经有主键了,显然不需要我们再去获得,所以我们这里处理的是当主键 ...
- Mybatis在insert操作时返回主键
今天在写项目的时候,遇到一个需求,就是在像数据库插入数据的时候,要保留插入数据的主键,以便后续进行级联时,可以将该主键作为另张表的外键. 但是在正常情况下我们使用插入语句返回的是int型,含义是影响该 ...
随机推荐
- Docker学习笔记 - Docker容器之间的连接
学习目标: 容器之间可以相互连接访问:: --link redis:redisAlias 准备工作 FROM ubuntu:14.04 RUN apt-get install -y ping RUN ...
- maven常见问题处理(3-3)Gradle编译时下载依赖失败解决方法
Gradle编译时在本地仓库中如果没有发现依赖,就会从远程仓库中下载, 默认的远程仓库为 mavenCentral(),即 http://repo1.maven.org/maven2/往往访问速度特别 ...
- H5的canvas绘图技术
canvas元素是HTML5中新添加的一个元素,该元素是HTML5中的一个亮点.Canvas元素就像一块画布,通过该元素自带的API结合JavaScript代码可以绘制各种图形和图像以及动画效果. 1 ...
- 复习HTML+CSS(2)
n 项目符号嵌套编号思路 标签的内容(文本.项目符号.表格.图片等)必须放在最底层标记中. n 图片标记(行内元素,单边标记) l 语法:<img 属性 = "值"&g ...
- python基础——类名称空间与对象(实例)名称空间
python基础--类名称空间与对象(实例)名称空间 1 类名称空间 创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性 而类的良好总属性:数据属性和函数属性 其中类 ...
- Hive&SqlServerql:inner join on条件中如果两边都是空值的情况下,关联结果中会把数据给过滤掉。
今天遇到的一个大坑,话不多少,看sql和下边的查询结果: --问题:恰好把buildingid is null的记录给过滤掉 ),buildingid ),)); ); ); ); ); ); ); ...
- Linux下内存问题检测神器:Valgrind
在写大型C/C++工程时难免会发生内存泄漏现象,系统编程中一个重要的方面就是有效地处理与内存相关的问题.你的工作越接近系统,你就需要面对越多的内存问题.有时这些问题非常琐碎,而更多时候它会演变成一个调 ...
- 学习React系列(九)——高阶函数
定义:高阶组件就是一个函数,且该函数接收一个组件作为参数,并返回一个新的组件. (上一篇已经说过了高阶组件可以用来解决交叉问题) 一.不要改变原始组件,使用组合 class A extends Rea ...
- RPO(Relative Path Overwrite)
Conception(Relative vs Absolute) Abosolute Path: "/etc/hosts"(in Linux), "C:\Windows\ ...
- [LeetCode] 2 Keys Keyboard 两键的键盘
Initially on a notepad only one character 'A' is present. You can perform two operations on this not ...