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. centos 7.X & centos6.X 防火墙基本命令

    Centos 7 firewall 命令:查看已经开放的端口: firewall-cmd --list-ports 开启端口 firewall-cmd --zone=public --add-port ...

  2. DotnetSpider (一) 架构的理解、应用、搭建

    第一次写博客,比较浅显,欢迎大牛们指点一二,不胜感激.   ** 温馨提示:如需转载本文,请注明内容出处.**   本文连接:http://www.cnblogs.com/grom/p/8931650 ...

  3. Spring异常之版本错误

    今天开始一个新项目的开发,结果使用maven刚刚部署完环境,一启动立马报错 java.lang.NoSuchMethodError: org.springframework.util.ClassUti ...

  4. PHP 5 Array 函数

    PHP Array 简介 PHP Array 函数允许您访问并操作数组. 支持简单的数组和多维数组. 安装 PHP Array 函数是 PHP 核心的组成部分.无需安装即可使用这些函数. PHP 5 ...

  5. 一例完全理解vue 2.0 的slots 和 functional render

    https://jsfiddle.net/pronan/mjqpmw0u/ 通过调节plan="bbb"的值, 比如换成plan="children",你会发现 ...

  6. webpack 1.x 配合npm scripts管理多站点

    需求场景: 希望通过一个webpack文件夹管理多个站点的打包流程. 假设现在我要为站点domain配置打包流程. npm 添加淘宝镜像 你懂得 vim ~/.npmrc registry = htt ...

  7. Bootstrap3 排版-标题

    HTML 中的所有标题标签,<h1> 到 <h6> 均可使用.另外,还提供了 .h1 到 .h6 类,为的是给内联(inline)属性的文本赋予标题的样式. h1. Boots ...

  8. WiFi文件上传框架SGWiFiUpload

    背景 在iOS端由于文件系统的封闭性,文件的上传变得十分麻烦,一个比较好的解决方案是通过局域网WiFi来传输文件并存储到沙盒中. 简介 SGWiFiUpload是一个基于CocoaHTTPServer ...

  9. 理解性能的奥秘——应用程序中慢,SSMS中快(2)——SQL Server如何编译存储过程

    本文属于<理解性能的奥秘--应用程序中慢,SSMS中快>系列 接上文:理解性能的奥秘--应用程序中慢,SSMS中快(1)--简介 本文介绍SQL Server如何编译存储过程并使用计划缓存 ...

  10. Android倒计时器——CountDownTimer

    Android倒计时器--CountDownTimer 说明 第一个参数是倒计时的时间 第二个参数是多长时间执行一次回调 /** * @param millisInFuture The number ...