读mybatis源码之十:主键生成KeyGenerator

      在mybatis里面经常遇到生成主键的问题,使用自增或者序列,保存对象后对象里面有主键值,来看看是怎么处理的:

1、在BaseStatementHandler里面有生成generateKeys,主要是执行: 

  protected void generateKeys(Object parameter) {
    KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
    ErrorContext.instance().store();
    keyGenerator.processBefore(executor, mappedStatement, null, parameter);
    ErrorContext.instance().recall();
  }
processBefore, 表示执行前处理,对应mapper里面的selectKey中的order="BEFORE"属性,先执行查询key,并设置到参数对象中。

2、在各个声明处理器中,update有代码:

KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
    keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
processAfter, 表示执行后处理, 对应mapper里面的selectKey中的order="AFTER"属性,表示执行后,再查一遍key,设置到参数对象中

3、KeyGenerator分Jdbc3KeyGenerator和SelectKeyGenerator

SelectKeyGenerator表示在mapper里面配置的 selectKey生成方式
Jdbc3KeyGenerator表示自增的,也就是数据库自增后如果需要知道值,就用这个,这个是将自增结果回填到对象中。
如果知道使用的是那个主键生成器呢?
在configuration里面有个参数useGeneratedKeys,这个默认是false
在看看MappedStatement对象里面:
 mappedStatement.keyGenerator = configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType) ? new Jdbc3KeyGenerator() : new NoKeyGenerator();
也就是说默认是NoKeyGenerator。
在mapper加载的时候,如果配置了 selectKey就用 SelectKeyGenerator生成器。见XMLStatementBuilder里面:
   if (configuration.hasKeyGenerator(keyStatementId)) {
      keyGenerator = configuration.getKeyGenerator(keyStatementId);
    } else {
      keyGenerator = context.getBooleanAttribute("useGeneratedKeys",
          configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType))
          ? new Jdbc3KeyGenerator() : new NoKeyGenerator();
    }
    builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
        fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
        resultSetTypeEnum, flushCache, useCache, resultOrdered,
        keyGenerator, keyProperty, keyColumn, databaseId, langDriver);

所以如果想用插入后有主键值,需要配置useGeneratedKeys为true。使用Jdbc3KeyGenerator生成器,或者使用SelectKey

你可能感兴趣的:(读源码)