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. Chrome的First Paint

    前言 First paint 直译过来的意思就是浏览器第一次渲染(paint),在First paint之前是白屏,在这个时间点之后用户就能看到(部分)页面内容. 所以研究这个First Paint的 ...

  2. Python自动化测试入门

    在当前自动化测试中,最火的语言就是Python,很容易上手.然后就是Java+testng+appium做的UI自动化测试.下面我们就用Python脚本,做自动化集成测试. (1)获取APK文件中ID ...

  3. 去除html标记和替换script标记

    1: /// <summary> 2: /// 去除HTML标记 3: /// </summary> 4: /// <param name="NoHTML&qu ...

  4. c++ 隐藏

    子类中写了一个与从父类中继承下来的方法名同名的方法 子类对象.方法();                    //调用子类中定义的方法 父类对象.方法();                    / ...

  5. ubuntu 卸载从源码安装的 emacs

    由于配置问题想卸了重装. 解压并进入你的源码所在目录: ./configure sudo make uninstall Done Reference: http://askubuntu.com/que ...

  6. 【python标准库模块五】Xml模块学习

    Xml模块 xml本身是一种格式规范,是一种包含了数据以及数据说明的文本格式规范.在json没有兴起之前各行各业进行数据交换的时候用的就是这个.目前在金融行业也在广泛在运用. 举个简单的例子,xml是 ...

  7. Dynamics CRM2016 Web API之删除单个查找字段值

    之前的博文中有介绍过,Web Api中的一个删除单个属性的Api但没提供查找字段的删除方法,本篇补充上,这里给出的示例代码是C#的(主要看url的拼接),看下url中最后的/$ref,这个标示表明了当 ...

  8. java 随机数高效生成

    分享牛,分享牛原创.近期去面试经常被问到java如何生产随机数,以及生成很大的字符串保证不能重复,还要考虑性能,之前本人面试别人的时候,可能不会问这个问题.既然这个java随机数问题经常被问到,那咱们 ...

  9. Android系统的安全设计与架构

    Android系统的安全设计与架构 一.安全策略 1.Android 的总体架构由5个主要层次上的组件构成,这5层是:Android应用层. Android框架层.Dalvik虚拟机层.用户空间原生代 ...

  10. 第三方开源动画库EasyAnimation中一个小bug的修复

    看过iOS动画之旅的都知道,其中在最后提到一个作者写的开源动画库EasyAnimation(以下简称EA). EA对CoreAnimation中的view和layer动画做了更高层次的包装和抽象,使得 ...