官网: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实现添加记录时返回主键值的更多相关文章

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

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

  2. MyBatis插入记录时返回主键id的方法

    有时候插入记录之后需要使用到插入记录的主键,通常是再查询一次来获取主键,但是MyBatis插入记录时可以设置成返回主键id,简化操作,方法大致有两种. 对应实体类: public class User ...

  3. mybatis添加数据时返回主键 insert 返回主键值

    insert 返回主键值 useGeneratedKeys=“true” parameterType=“USer” keyProperty=“id”, <insert id="inse ...

  4. mybatis 08: 返回主键值的insert操作 + 利用UUID获取字符串(了解)

    返回主键值的insert操作 应用背景 图示说明 在上述业务背景下,涉及两张数据表的关联操作:用户表 + 用户积分表 传统操作:在对用户表执行完插入语句后,再次查询该用户的uid,将该uid作为外键, ...

  5. MyBatis在Oracle中插入数据并返回主键的问题解决

    引言:  在MyBatis中,希望在Oracle中插入数据之时,同一时候返回主键值,而非插入的条数... 环境:MyBatis 3.2 , Oracle. Spring 3.2   SQL Snipp ...

  6. [oracle] 如何使用myBatis在数据库中插入数据并返回主键

    在MyBatis中,希望在Oracle中插入数据的同时返回主键值,而非插入的条数. ① oracle使用 selectKey. U_USER_INFO_SEQ 是在数据库中定义好的这张表关联的序列se ...

  7. MyBatis在insert插入操作时返回主键ID的配置

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

  8. mybatis 插入数据时返回主键

    在使用MyBatis做持久层时,insert语句默认是不返回记录的主键值,而是返回插入的记录条数:显然,假如主键是你生成后插入的,自然你已经有主键了,显然不需要我们再去获得,所以我们这里处理的是当主键 ...

  9. Mybatis在insert操作时返回主键

    今天在写项目的时候,遇到一个需求,就是在像数据库插入数据的时候,要保留插入数据的主键,以便后续进行级联时,可以将该主键作为另张表的外键. 但是在正常情况下我们使用插入语句返回的是int型,含义是影响该 ...

随机推荐

  1. Spark入门(1-1)什么是spark,spark和hadoop

    一.Spark是什么? Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎,可用来构建大型的.低延迟的数据分析应用程序. Spark是UC Berkeley AMP lab (加 ...

  2. maven常见问题处理(3-2)maven打包时跳过测试的几个方法

    运行mvn install时跳过Test方法一:<project> [...] <build> <plugins> <plugin> <group ...

  3. SpringBoot使用log4j

    1.添加log4j相关依赖 在pom.xml文件中添加相关依赖: <!--配置log4j--> <dependency> <groupId>org.springfr ...

  4. jenkins创建pipeline

    新建任务的时候,有两个流水线相关的任务类型,如下图.其中:流水线更加针对单主干模式的开发,在主干目录下放一个Jenkinsfile文件,其中该文件保存了从SCM拉代码.构建.测试.发布等等流程. 而M ...

  5. __new__ 单例

    a.实例化类 实例化一个类时 1. 创建一个对象,调用__new__方法,如果没有会调用父类的__new__方法 2. 调用__init__方法 3. 返回对象的引用 class Dog(object ...

  6. Hibernate(十六):Hibernate二级缓存

    Hibernate缓存 缓存(Cache):计算机领域非常通用的概念.它介于应用程序和永久性数据存储源(如磁盘上的文件或者数据库)之间,起作用是降低应用程序直接读取永久性数据存储源的频率,从而提高应用 ...

  7. Node.js的安装以及Node.js的模块管理

    索引: Node.js的安装以及Node.js的模块管理Node.js开发环境搭建以及对ES6的支持Node.js构建Vue.js项目Vue.js单文件组件的开发基于Vue.js的UI组件(Eleme ...

  8. [CVPR2018] Context-aware Deep Feature Compression for High-speed Visual Tracking

    基于内容感知深度特征压缩的高速视觉跟踪 论文下载:http://cn.arxiv.org/abs/1803.10537对于视频这种高维度数据,作者训练了多个自编码器AE来进行数据压缩,至于怎么选择具体 ...

  9. [学习笔记]15个QA让你快速入门51单片机开发

    一.C语言相关 Q1:sbit与sfr代表是什么?有什么作用? Q2:#define OSC_FREQ  22118400L这句宏命令里的“L”是什么意思? Q3:我粘贴了别人的代码,怎么发现没有un ...

  10. hermite矩阵

    在读线代书.因为之前并没有上过线性代数的课.所以决定把基础打牢牢. 读书的时候当然会出现不懂的概念和术语或者定理什么的.所以在这记录一下啦--- hermit矩阵要理解它好像先要知道什么是共轭(con ...