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. map内置函数、lambda表达式、快捷生成想要的列表、filter内置函数

      map函数                             语法 map(function, iterable, ...) 参数 function -- 函数,有两个参数 iterable ...

  2. 009.Working with SQL Server LocalDB --【在sql server localdb 上操作数据】

    Working with SQL Server LocalDB 在sql server localdb 上操作数据 2017-3-7 2 分钟阅读时长 本文内容 1.SQL Server Expres ...

  3. ACM 最小公倍数

    给定两个正整数,计算这两个数的最小公倍数. Input 输入包含多组测试数据,每组只有一行,包括两个不大于1000的正整数.Output对于每个测试用例,给出这两个数的最小公倍数,每个实例输出一行.  ...

  4. 高仿腾讯QQ最终版

    之前写过一篇关于高仿腾讯QQ的博客,不知道的看这:http://blog.csdn.net/htq__/article/details/51840273 ,主要是从界面上高仿了腾讯QQ,在UI上基本上 ...

  5. java中static特殊性和final(static成员直接被访问,this不能用在static方法中,static不可访问非static)

    java的static关键字 java中,static修饰的成员变量和成员方法叫静态变量和静态方法,不依赖类特定的实例,被类的所有实例共享. 静态变量或类变量 和 实例变量,区别是: 静态变量在内存中 ...

  6. Hadoop2动态调整Log级别-以datanode的heartbeat log为例

    在Hadoop中,有些log信息在正常情况下是不打印出来的.比如datanode发送heartbeat的日志. 代码位于BPServiceActor#sendHeartBeat方法中,如下图: 由于默 ...

  7. Xcode 8新功能介绍

    概述 Xcode 8正式版在9月13日已经推送给开发者下载,下载之后就出现了很多编译错误,之前的插件也不能用了,但是发现Xcode8把好多不错的插件功能整合到自身了,感觉这点也挺不错. 结合自己遇到的 ...

  8. Nagle算法

    简介 Nagle算法是以他的发明人John Nagle的名字命名的,它用于自动连接许多的小缓冲器消息:这一过程(称为nagling)通过减少必须发送包的个数来增加网络软件系统的效率.Nagle算法于1 ...

  9. 2.Cocos2dx 3.2中的重力系统Box2D

     1 添加Box2D相关的库 步骤1:右击项目所在的解决方案à添加->现有项目àE:\Installed\cocos2d-x-3.2\cocos2d-x-3.2\external\Box2D ...

  10. Android简易实战教程--第二十五话《网络图片查看器》

    访问网络已经有了很成熟的框架.这一篇只是介绍一下HttpURLConnection的简单用法,以及里面的"注意点".这一篇可以复习或者学习HttpURLConnection.han ...