Mybatis提供了主键生成器接口KeyGenerator,insert语句默认是不返回记录的主键值,而是返回插入的记录条数;如果业务层需要得到记录的主键时,可以通过配置的方式来完成这个功能 。

由于不同的数据库对主键的生成不一样:

(1)针对Sequence主键而言,在执行insert sql前必须指定一个主键值给要插入的记录,如Oracle、DB2,KeyGenerator提供了processBefore()方法。

(2)针对自增主键的表,在插入时不需要主键,而是在插入过程自动获取一个自增的主键,比如MySQL,Postgresql,KeyGenerator提供了processAfter()方法。

KeyGenerator源码如下:

/**
 * @author Clinton Begin
 */
public interface KeyGenerator {

  //在执行insert之前,设置属性order="BEFORE"
  void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter);

  //在执行insert之后,设置属性order="AFTER"
  void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter);

}

KeyGenerator分别实现了Jdbc3KeyGenerator、SelectKeyGenerator和NoKeyGenerator,其中NoKeyGenerator并没有具体的操作,不需要去关心。

KeyGenerator的实现类如下:

主键生成器的配置方式有两种

(一)当数据库可以自增主键时,如mysql,可以采用如下配置:

<insert id="save" useGeneratedKeys="true" keyColumn="i_id" keyProperty="id">
<span style="white-space:pre">	</span>insert into tbl_log (log_type,log_info) values (#{logType},#{logInfo})
</insert>

这样就是在返回值中带有生成数据的主键,在insert语句调用之后执行,应该是调用的是processAfter方法,并且默认使用的实现类是Jdbc3KeyGenerator,它也只是实现了processAfter方法

(二)当数据库需要执行Sequence主键时,需要另外一种配置,MySQL也可以使用Sequence主键,配置如下:

<insert id="save">
<selectKey resultType="int" keyProperty="id" order="AFTER">
		 SELECT LAST_INSERT_ID() AS id
	</selectKey>
	insert into tbl_log (log_type,log_info) values
	    (#{logType},#{logInfo})
</insert>

通过配置我们可以看到,order=AFTER,这样是在执行完insert语句之后再获得最大id,在Oracle下需要配置成oder=BEFORE了,我们可以猜到这时候使用的是SelectKeyGenerator,接下来我们会对这个两个实现类进行具体的分析。

在SimpleStatementHandler执行具体的update函数时,会进行选择执行Jdbc3KeyGenerator或者SelectKeyGenerator,或者不执行任何KeyGenerator,代码如下:

@Override
  public int update(Statement statement) throws SQLException {
    String sql = boundSql.getSql();
    Object parameterObject = boundSql.getParameterObject();
    KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
    int rows;
    if (keyGenerator instanceof Jdbc3KeyGenerator) {
      statement.execute(sql, Statement.RETURN_GENERATED_KEYS);
      rows = statement.getUpdateCount();
      keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
    } else if (keyGenerator instanceof SelectKeyGenerator) {
      statement.execute(sql);
      rows = statement.getUpdateCount();
      keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
    } else {
      statement.execute(sql);
      rows = statement.getUpdateCount();
    }
    return rows;
  }

在PreparedStatementHandler中执行update函数时,则使用如下方法:

 @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;
  }

所以其实可以看到执行的都是processAfter方法,其实具体的调用顺序并不是的根据KeyGenerator的processBefore和processAfter来实现的。

MyBatis主键生成器KeyGenerator(一)的更多相关文章

  1. MyBatis主键生成器SelectKeyGenerator(三)

    前面两篇博客我们介绍了MyBatis主键生成器KeyGenerator(一)和MyBatis主键生成器Jdbc3KeyGenerator(二),接下来我们介绍SelectKeyGenerator, 如 ...

  2. MyBatis主键生成器Jdbc3KeyGenerator(二)

    上一篇博客MyBatis主键生成器KeyGenerator(一)中我们大体介绍了主键生成器的接口及配置等,接下来我们介绍一下KeyGenerator的实现类Jdbc3KeyGenerator Jdbc ...

  3. 轻量级封装DbUtils&Mybatis之四MyBatis主键

    MyBatis主键 不支持对象列表存储时对自增id字段的赋值(至少包括3.2.6和3.3.0版本),如果id不是采用底层DB自增主键赋值,不必考虑此问题 温馨提示:分布式DB环境下,DB主键一般会采用 ...

  4. Hibernate各种主键生成器策略与配置详解(转载)

    http://www.cnblogs.com/kakafra/archive/2012/09/16/2687569.html 1.assigned 主键由外部程序负责生成,在 save() 之前必须指 ...

  5. Hibernate主键生成器

    主键生成器负责生成数据表记录的主键:increment:为long,short或者int类型主键生成唯一标识.只有在没有其他进程往同一张表中插入数据时才能使用.在集群下不能使用! identity:在 ...

  6. 主键生成器效率提升方案|基于雪花算法和Redis控制进程隔离

    背景 主键生成效率用数据库自增效率也是比较高的,为什么要用主键生成器呢?是因为需要insert主表和明细表时,明细表有个字段是主表的主键作为关联.所以就需要先生成主键填好主表明细表的信息后再一次过在一 ...

  7. MyBatis主键返回

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

  8. mybatis 主键UUID生成策略

    <insert id="insert" parameterType="com.lsfwpt.lawmis.po.SysUser"> <sele ...

  9. Hibernate中的主键生成器generator

    本文讲述Hibernate的generator属性的意义.Generator属性有7种class,本文简略描述了这7种class的意义和用法. [xhtml] view plaincopy <c ...

随机推荐

  1. Linux学习之CentOS(一)--CentOS6.5环境搭建

    一.前言 作为一个从事运维工作好几年的老运维来说,linux系统怎能不学呢?所以,这几天自己准备学习一下linux操作系统.废话不多说,直奔主题. 要学linux开发,首先得要安装linux系统吧,这 ...

  2. 零开始:NetCore项目权限管理系统:定义基本接口和实现

    上一篇讲了基础的框架搭建    地址:http://www.cnblogs.com/fuyu-blog/p/8909779.html 这篇主要讲解SqlSugar   ORM的数据库连接以及建表和接口 ...

  3. oracle初试、函数、增删改查、多表查询

      安装oracle后的测试以及解锁账户                  安装后打开命令行,输入 sqlplus 回车后会提示输入用户名,输入 sys或者system 回车后输入密码,密码为安装or ...

  4. hibernate实体对象的三种状态:自由状态,持久状态,游离状态.

    自由态与游离态的区别: 当一个持久化对象,脱离开Hibernate的缓存管理后,它就处于游离状态,游离对象和自由对象的最大区别在于,游离对象在数据库中可能还存在一条与它 对应的记录,只是现在这个游离对 ...

  5. ArrayList源码和多线程安全问题分析

    1.ArrayList源码和多线程安全问题分析 在分析ArrayList线程安全问题之前,我们线对此类的源码进行分析,找出可能出现线程安全问题的地方,然后代码进行验证和分析. 1.1 数据结构 Arr ...

  6. Linux 查看CPU温度

    安装 lm-sensors sudo apt-get install lm-sensors # 安装yes | sudo sensors-detect # 侦测所有感测器 sensors # 查看温度 ...

  7. VUE相关资料合集

    ===官方=== https://github.com/vuejs/vue vue-components组件库 ---PC端--- https://github.com/ElemeFE/element ...

  8. 利用Filter和拦截器,将用户信息动态传入Request方法

    前言: 在开发当中,经常会验证用户登录状态和获取用户信息.如果每次都手动调用用户信息查询接口,会非常的繁琐,而且代码冗余.为了提高开发效率,因此就有了今天这篇文章. 思路: 用户请求我们的方法会携带一 ...

  9. CRM客户关系管理系统(八)

    第八章.只读字段处理和filter_horizontal的实现  8.1.只读字段的处理 (1)kingadmin/admin_base.py # kingadmin/admin_base.py cl ...

  10. 使用POI实现报表打印功能

    [版权申明:本文系作者原创,转载请注明出处] 文章出处:http://blog.csdn.net/sdksdk0/article/details/53393453 作者:朱培 ID:sdksdk0 这 ...