MyBatisのソース解析--ResultSetHandler

ResultSetHandler

結果オブジェクトがResultSetにマップされたデータベースを返すために責任があります

public interface ResultSetHandler {

//处理结果集,生成对应的结果对象集
  <E> List<E> handleResultSets(Statement stmt) throws SQLException;

//处理结果集,生成对应的游标对象集
  <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException;

//处理存储过程的输出参数
  void handleOutputParameters(CallableStatement cs) throws SQLException;

}

DefaultResultSetHandler

デフォルトの実装ResultSetHandler実装クラス分析インターフェイスは、分析の後に基づいています

ResultSetWrapper

DefaultResultSetHandler直接メタデータの一部は、各列のResultSetとして、ResultSetWrapperのResultSetとアシストの対応方法を記録し、ResultSetを取得に使用されるが、その後の使用のためResultSetWrapperとしてパッケージ化されません

  • 列名(コンストラクタ初期化)
  • Java型(コンストラクタ初期化)
  • JDBCタイプ(コンストラクタ初期化)
  • 設定し、対応するtypeHandler
  • 列名は、明示的にコレクションをマッピングし
  • 列名が明示的にマッピングされていない(つまり、このresultMap列マッピングを設定していません)
  • ......

loadMappedAndUnMappedColumnNames()、マッピングこのresultMap比較で指定されたResultSet ColumnNameの列名を横断キー列名IDのプレフィックスとこのresultMapにmappedMap / unmappedMapに添加しました

シンプルマッピング

handleResultSet()が指定された使用又はResultSetHandler ResultSetをデフォルトhandleRowValuesは()は、2つを含む方法がhandleRowValuesForNestedResultMap()とhandleRowValuesForSimpleResultMap()内にネストされたか否かに応じて、具体的な方法です。

非入れ子のマッピング

コアメソッドhandleRowValuesForSimpleResultMap()

private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
      throws SQLException {
    DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
    skipRows(rsw.getResultSet(), rowBounds);
    while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
      ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
      Object rowValue = getRowValue(rsw, discriminatedResultMap);
      storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
    }
  }

図6に示すフローチャートを実行します。

ここに画像を挿入説明

次のステップ:

  1. 行のRowBoundsは、指定の位置を特定するオフセット
  2. マッピングされたレコードが存在する必要があるかどうかを検出
  3. マッピングはResultMapId弁別識別型が返されるオブジェクトこのresultMapを使用して決定されます
  4. マッピングのResultSetの行
    。結果オブジェクトの作成
    の自動マッピング開くかどうか、B。を判断し
    、Cを自動的列をマップは、明示的にマップされていない
    明示的にマップされた、D。マップされた列
  5. 保存ResultHandlerで得られた結果にオブジェクトをマッピングされました

オブジェクトを格納するための結果resultHandler

skipRows

rowBounds ResultSet.nextによると、繰り返し指定されたレコードへのオフセット()メソッドを呼び出し

shouldProcessMoreRows

DefaultResultContextオブジェクトを使用して結果を決定格納、オブジェクトの数がカウントされ、マッピングを続行するかどうかをDefaultResultContext.isStopped()カウントrowBounds.limit()比較の結果を比較することによって結果、

resolveDiscriminatedResultMap

識別型はResultMapIdマッピングオブジェクトを決定するために使用返さresultmapに

getRowValue
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
    final ResultLoaderMap lazyLoader = new ResultLoaderMap();
    Object rowValue = createResultObject(rsw, resultMap, lazyLoader, null);
    if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
      final MetaObject metaObject = configuration.newMetaObject(rowValue);
      boolean foundValues = this.useConstructorMappings;
      if (shouldApplyAutomaticMappings(resultMap, false)) {
        foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;
      }
      foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;
      foundValues = lazyLoader.size() > 0 || foundValues;
      rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
    }
    return rowValue;
  }
  1. createResultObjectの
    4つのシナリオの合計

private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix)
      throws SQLException {
    final Class<?> resultType = resultMap.getType();
    final MetaClass metaType = MetaClass.forClass(resultType, reflectorFactory);
    final List<ResultMapping> constructorMappings = resultMap.getConstructorResultMappings();
    if (hasTypeHandlerForResultObject(rsw, resultType)) {
    //第一种
      return createPrimitiveResultObject(rsw, resultMap, columnPrefix);
    } else if (!constructorMappings.isEmpty()) {
    //第二种
      return createParameterizedResultObject(rsw, resultType, constructorMappings, constructorArgTypes, constructorArgs, columnPrefix);
    } else if (resultType.isInterface() || metaType.hasDefaultConstructor()) {
    //第三种
      return objectFactory.create(resultType);
    } else if (shouldApplyAutomaticMappings(resultMap, false)) {
    //第四种
      return createByConstructorSignature(rsw, resultType, constructorArgTypes, constructorArgs, columnPrefix);
    }
    throw new ExecutorException("Do not know how to create an instance of " + resultType);
  }

  • 最初の結果セットが一つだけあり、typeHandlerの第1のタイプは、ダイレクトコンバージョン(例えば、年齢のみチェック、デジタルにバックを使用して、このオブジェクトおよびオブジェクトを取得し、値型を変換typeHandler resultTypeとを挙げることができます、直接)int型を返す型に変換
  • 第二:に記録されたこのresultMap <Constructor>ノード情報、適切な構成を選択する反射法により作成されたオブジェクト
  • 第三:使用引数なしのデフォルトコンストラクタ、ObjectFactoryを持つオブジェクトを作成します
  • 第四には:適切なコンストラクタを見つけるための自動マッピングにより、我々はコンストラクタに@AutoMapConstructor注釈を追加する必要があります。構造パラメーターと結果の方法は、同一種類のコンストラクタを呼び出すことと、タイプと一致し(第二に、第一、第二1相当に対応する最初の)同じデータシーケンスに集中され、オブジェクトの特性が得られ値が間違っている可能性がありますが、プロパティ値がマッピングプロセスの後半でエラーが上書きされます。
ApplyAutomaticMappings

マッピング関係を明示的に(例えば、直接resultTypeと指定された)このresultMapの属性に指定されていない規則MyBatisのに応じては下線こぶをオンに自動的にマッチングされ、次のように、そのマッチングプロセスです。

  1. すべての列名のセットを取得することは、明示的にResultSetWrapperからにマッピングされていません
  2. コレクションを横断し、接頭辞を指定するためにすることは、対応する下線の属性名は、こぶを転送し得るために除去されます
  3. setterメソッドは、メタオブジェクトのための反射属性チェックを使用しています
  4. typeHandlerの対応するタイプを探します
  5. (記載されている、属性名とtypeHandler含む)UnMappedColumnAutoMapping構成オブジェクト
  6. 値の反射を設定するために使用される5トラバーサルリスト
applyPropertyMappings
  1. 明示的ResultSetWrapperからマッピングされたすべての列名のセットを取得します。
  2. このresultMapからPropertyResultMappingsコレクションを取得します。
  3. getPropertyMappingValue()は、属性の値、および反射によって提供される値を取得し、3つのケースがあります
  • 複雑なオブジェクト、ネスティングプロセスの必要性のために
  • プリミティブ型の場合は、値を取得するために直接使用typeHandler
  • マルチ結果セットのシーン
storeObject

レコードはマッピング搬出、ResultHandler.listに結果オブジェクトに保存されます

ネストされたマッピング

コア法handleRowValuesForNestedResultMap()
は、次の手順:

  1. 行のRowBoundsは、指定の位置を特定するオフセット

  2. マッピングされたレコードが存在する必要があるかどうかを検出

  3. マッピングはResultMapId弁別識別型が返されるオブジェクトこのresultMapを使用して決定されます

  4. createKey()レコードが生成cacheKeyであることにより、

  5. 辞書nestedResultObjectsに保存されているcacheKey半製品を探します

  6. 検出ResultOrderedプロパティ

  7. getRowValueネストされたマッピングプロセス

    (外側のオブジェクトが存在しない場合nestedResultObjects.get() != null

    。結果オブジェクトの作成
    Bを。明示列マッピングされているか否かを決定するために、自動マッピングプロセスを開くかどうかを判定する
    Cを。処分明示的にマップされた列
    D。プレイス結果オブジェクトコレクションancestorObjectsの中に入れ
    、E。)(applyNestedResultMappingsを呼び出す次の層を処理しますこの方法で得られた、ネストされたマッピング結果オブジェクトは、外側ancestorObjectsコレクションオブジェクトに注入される場所、戻りの端
    F。オブジェクトの外側の組ancestorObjects除去
    グラム。nestedResultObjectsにおける半製品へのオブジェクトの

    あれば
    行っD、E、Fのステップは、

  8. マッピングが行われ、storeObject結果オブジェクトはResultHandlerに置か

createKey

それぞれのResultSet CacheKeyはnestedResultObjectsのハッシュマップの存在下で、キーとして作成され、地図オブジェクトが半オブジェクトはここ半オブジェクトを探して処理優先度セットの結果に格納され、現在のネストされたマッピングするための命令がある場合、現在の結果は、プロパティにターゲット層(すなわち、半オブジェクト)に注入する必要があります。
どのように対応する外側及び内側層に外部このresultMapは同じに扱われることを保証するために?それはcacheKeyと同じですか?
次のようにルールがある作成cacheKey:

  1. ResuleMapId + <id>/<idArg>ノード+カラム名に対応する値に対応
  2. 明確にマッピングされたカラム名と対応する値をこのresultMap
  3. マップタイプのresultTypeとする場合、すべての列名と対応する値
  4. ないresultTypeとタイプ地図、および値に対応する列名がマップされていない場合

上記の規則は、グローバルに一意CacheKeyにまとめ、その外CacheKeyのCacheKeyを作成しました

ResultOrdered

値がtrueの場合、外側のネストされたオブジェクトの横の端部を処理する各外層マッピングオブジェクトがnestedResultObjectsケースになり、メモリが途中でメモリが現れるのアウトを回避するために、保存することができ

レイジーローディング

オブジェクトの特定の特性、使用中のメモリにロードされ、プロキシのMyBatisのダイナミック形および使用中の実際のデータを取得するオブジェクトのプロキシオブジェクト遅延ロードプロパティ、プロキシオブジェクトを行うデータベースの負荷を返します。
ネストされたクエリの遅延をロード、ネストされたクエリとクエリはこのresultMapで定義された2つの主要異なるstatemetnです。メインクエリ結果が最終的にマッピングされている場合、現在の位置を決定する解像度マッピングネストされたクエリは、まだ遅延ロードされた構成に基づいてネストされたクエリの実行を遅らせることになります

遅延ロードされたコンフィギュレーション:

  1. 遅延の負荷に応じ性が決定されているかどうかを、明示的に設定fetchTypeプロパティをこのresultMap
  2. MyBatisの-config.xmlの<setting name="lazyLoadingEnabled" value = "true">開口遅延ローディングスイッチ
  3. でMyBatisの-config.xmlの<setting name="aggressiveLazyLoading" value = "false">すべての遅延特性がロードされますロード、ロードを得た真の怠惰な性質がある時、デフォルトはfalse
ResultLoaderMap和ResultLoader

すべての情報を保存ResultLoader中核アプローチは、遅延ロードを使用loadResult()メソッドであると、構成オブジェクト、エグゼキュータ、SQL文、タイプ、CacheKey含む遅延読み込みを行う執行SQL文を実行し、オブジェクトを返します

ResultLoaderMap(HashMapの<文字列、ロードペア>)に格納されたオブジェクトの属性とそれに対応するローディング遅延ResultLoaderオブジェクトloadMapフィールドを使用する、キー属性名(大文字LOADALL)と負荷()メソッドは、その呼び出しLoadPair.loadが設けられています()メソッドは、最終ポイントResultLoader.loadResult()メソッド

リスト内の現在の方法は、その後、ロードが遅れた場合ResultLoaderMapプロキシオブジェクトは、メソッドと遅延ロードの出発リストを保持します。

遅延ロードを反映

applyPropertyMappings()メソッドの呼び出しgetPropertyMappingValue()プロパティ値を取得し、遅延ロードかどうかを検出し、デフォルトJavasistProxyFactoryでプロキシオブジェクトを作成します

図に示すように。
ここに画像を挿入説明

公開された98元の記事 ウォンの賞賛9 ビュー10000 +

おすすめ

転載: blog.csdn.net/Mutou_ren/article/details/102794613