讀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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章