官网: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. Docker学习笔记 - Docker容器之间的连接

    学习目标: 容器之间可以相互连接访问:: --link redis:redisAlias 准备工作 FROM ubuntu:14.04 RUN apt-get install -y ping RUN  ...

  2. maven常见问题处理(3-3)Gradle编译时下载依赖失败解决方法

    Gradle编译时在本地仓库中如果没有发现依赖,就会从远程仓库中下载, 默认的远程仓库为 mavenCentral(),即 http://repo1.maven.org/maven2/往往访问速度特别 ...

  3. H5的canvas绘图技术

    canvas元素是HTML5中新添加的一个元素,该元素是HTML5中的一个亮点.Canvas元素就像一块画布,通过该元素自带的API结合JavaScript代码可以绘制各种图形和图像以及动画效果. 1 ...

  4. 复习HTML+CSS(2)

    n  项目符号嵌套编号思路 标签的内容(文本.项目符号.表格.图片等)必须放在最底层标记中. n  图片标记(行内元素,单边标记) l  语法:<img 属性 = "值"&g ...

  5. python基础——类名称空间与对象(实例)名称空间

    python基础--类名称空间与对象(实例)名称空间 1 类名称空间 创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性 而类的良好总属性:数据属性和函数属性 其中类 ...

  6. Hive&SqlServerql:inner join on条件中如果两边都是空值的情况下,关联结果中会把数据给过滤掉。

    今天遇到的一个大坑,话不多少,看sql和下边的查询结果: --问题:恰好把buildingid is null的记录给过滤掉 ),buildingid ),)); ); ); ); ); ); ); ...

  7. Linux下内存问题检测神器:Valgrind

    在写大型C/C++工程时难免会发生内存泄漏现象,系统编程中一个重要的方面就是有效地处理与内存相关的问题.你的工作越接近系统,你就需要面对越多的内存问题.有时这些问题非常琐碎,而更多时候它会演变成一个调 ...

  8. 学习React系列(九)——高阶函数

    定义:高阶组件就是一个函数,且该函数接收一个组件作为参数,并返回一个新的组件. (上一篇已经说过了高阶组件可以用来解决交叉问题) 一.不要改变原始组件,使用组合 class A extends Rea ...

  9. RPO(Relative Path Overwrite)

    Conception(Relative vs Absolute) Abosolute Path: "/etc/hosts"(in Linux), "C:\Windows\ ...

  10. [LeetCode] 2 Keys Keyboard 两键的键盘

    Initially on a notepad only one character 'A' is present. You can perform two operations on this not ...