最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis?handleResultSet結(jié)果集解析過程示例

 更新時間:2023年02月16日 14:40:07   作者:念念清晰  
這篇文章主要為大家介紹了MyBatis?handleResultSet結(jié)果集解析過程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前置知識

mybatis版本: 3.5.12

之前說到mybatis執(zhí)行完SQL后的結(jié)果集是由DefaultResultHandler組件的handleResultSets處理的。今天就來探討下這個重要的方法,該方法非常核心,而且內(nèi)容比較多,所以單拎出來一章。而上文DefaultResultHandler處理結(jié)果集的大致流程請參考:MyBatis ResultSetHandler 結(jié)果集的解析過程

在理解handleResultSets是怎么對結(jié)果集進行處理時,需要明白MyBatis中這么幾個組件

  • ResultMap和ResultMapping
  • ResultHandler和ResultContext
  • ResultLoaderMap和ResultLoader(這些是延時加載相關(guān))
  • ProxyFactory(延時加載相關(guān),用來為延時加載對象創(chuàng)建代理對象使用的)

ResultMap和ResultMapping

我們經(jīng)常使用MyBatis的xml文件配置SQL信息,在select標簽上有一個屬性是resultMap,它會指向一個resultMap標簽,resultMap標簽示例如下

<resultMap id="usermap" type="user" autoMapping="true">
    <!--關(guān)閉自動映射,那么沒有指定的列名不會出現(xiàn)在結(jié)果集中-->
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <result property="birthday" column="birthday"/>
    <result property="password" column="password"/>
</resultMap>

mybatis中每個resultMap標簽會被解析成ResultMap對象。而resultMap標簽中的idresultconstructor這3種子標簽會被解析成ResultMapping對象(id其實就是特殊的result標簽)。

接下來我們來看下ResultMap的重要組成部分

public class ResultMap {
  private Configuration configuration;
  // 唯一ID,一般是namespace+resultMap標簽的ID
  private String id;
  // 對應(yīng)的Java類型
  private Class<?> type;
  // resultMap標簽中的result標簽的集合
  private List<ResultMapping> resultMappings;
  // resultMap標簽中的id標簽的集合
  private List<ResultMapping> idResultMappings;
  // resultMap標簽中的constructor標簽的集合
  private List<ResultMapping> constructorResultMappings;
  // resultMap標簽中所有子標簽的集合
  private List<ResultMapping> propertyResultMappings;
  // 結(jié)果集中列名
  private Set<String> mappedColumns;
  // 對應(yīng)的Java對象的屬性名
  private Set<String> mappedProperties;
  // discriminator鑒別器會單獨被解析成該對象
  private Discriminator discriminator;
  // 是否是嵌套映射
  private boolean hasNestedResultMaps;
  // 是否嵌套查詢
  private boolean hasNestedQueries;
  // 是否自動映射
  private Boolean autoMapping;
}

其中比較重要的幾個屬性就是

  • resultMappings:它表示resultMap標簽中的result標簽的集合(包含id標簽)后續(xù)結(jié)果集的解析過程避免不了會遍歷它
  • hasNestedResultMaps:是否由嵌套映射,一般都是resumtMap標簽中含有collection標簽association標簽才會為true,后面介紹到嵌套映射會分析。

ResultHandler和ResultContext

在mybatis的解析過程中,我們很容易想象到它是遍歷結(jié)果集然后和resultMap標簽的映射關(guān)系進行比較,最終生成結(jié)果集對象。那么遍歷結(jié)果集其實就是對一條一條數(shù)據(jù)進行單獨處理。處理完一條記錄,就把這條記錄對應(yīng)的對象添加到一個集合中,最終獲取這個集合就是用戶想要得到的對象。

ResultContext用來在上下文中傳遞解析過后的單個對象,ResultHandler內(nèi)部有一個List集合用來存儲單條數(shù)據(jù)解析后的對象的。他們的源碼非常簡單易懂,首先我們來看DefaultResultHandler(ResultHandler的實現(xiàn)類)的源碼

public class DefaultResultHandler implements ResultHandler<Object> {
  private final List<Object> list;
  @Override
  public void handleResult(ResultContext<?> context) {
    list.add(context.getResultObject());
  }
  public List<Object> getResultList() {
    return list;
  }
}

它只有一個屬性listlist就是用來存儲解析單條數(shù)據(jù)后的對象。它還提供了兩個方法

  • handleResult:就是把上下文中單條數(shù)據(jù)處理后的對象存入到list集合中。
  • getResultList:獲取結(jié)果集解析過后的list,也就是用戶最終需要的list對象。

接下來來看下ResultContext這個上下文對象

public class DefaultResultContext<T> implements ResultContext<T> {
  private T resultObject;
  private int resultCount;
  private boolean stopped;
  public T getResultObject() {
    return resultObject;
  }
  public void nextResultObject(T resultObject) {
    resultCount++;
    this.resultObject = resultObject;
  }
}

它由三個屬性:

  • resultObject:用來保存當(dāng)前解析的這條記錄的結(jié)果
  • resultCount:結(jié)果集的數(shù)量,每解析完一條記錄,該值加一
  • stopped:是否停止解析,當(dāng)?shù)阶詈笠粭l記錄時,該值為false

它的兩個方法比較簡單,就不再說了。

接下來我們正式進入mybatis解析結(jié)果集的核心代碼分析。mybatis解析結(jié)果集可以分為兩大類:一是簡單映射、而是嵌套映射。接下來我們即從這兩個方面研究

簡單映射

接下來就來看下本文主題handleResultSet方法的核心邏輯

private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
    if (parentMapping != null) {
      // 1. 處理resultSets標簽的邏輯
      handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
    } else {
      // 2. 正常處理resultMap標簽。將結(jié)果集中的記錄映射為指定對象??赡苌婕暗角短子成?。
      if (resultHandler == null) {
        // 默認都會走進該分支。
        // ResultSet是個集合嘛,那Result自然就是集合中的一條記錄啦。DefaultResultHandler是用來處理單條Result記錄的。
        DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
        // 處理多行記錄的方法(重要?。。。。。。。?
        handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
        multipleResults.add(defaultResultHandler.getResultList());
      } else {
        // 如果用戶自定義了 resultHandler 使用用戶自定義的
        handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
      }
    }
}

這個方法簡介明了,它的執(zhí)行流程是這樣的:

第一步:判斷parentMapping是否存在值。而這個分支是專門為解析resultSets標簽使用的分支,其實和普通的解析結(jié)果集沒什么不同。等看完后面的解析過程再回過頭看就理解了。這個分支不重要,我們繼續(xù)往下走

第二步:判斷用戶是否指定resultHandler類型,一般都是不會指定的,所以他會走第一個分支。創(chuàng)建一個默認的ResultHandler,然后執(zhí)行handleRowValues方法

第三步:如果用戶指定resultHandler類型,就執(zhí)行handleRowValues方法

可以發(fā)現(xiàn)無論是哪個分支,最終都會走到handleRowValues方法,從名字也能看出,該方法的邏輯是處理多行數(shù)據(jù)。接下來我們就來看下DefaultResultSetHandler#handleRowValues方法

handleRowValues

public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler&lt;?&gt; resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
  if (resultMap.hasNestedResultMaps()) {
    ensureNoRowBounds();
    checkResultHandler();
    // 處理嵌套映射
    handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
  } else {
    // 處理簡單映射
    handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
  }
}

該方法只做了一件事情,那就是判斷結(jié)果集是否是嵌套映射的。這取決于xml文件中resultMap標簽是否定義了collectionassociation標簽。這里我們先討論簡單映射的場景。所以接下來我們來看DefaultResultSetHandler#handleRowValuesForSimpleResultMap方法。從名字也可以看出,該方法的邏輯是處理簡單映射。簡單映射不會涉及延遲加載等復(fù)雜的邏輯,所以源碼很好理解

handleRowValuesForSimpleResultMap

private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
    throws SQLException {
  // 第一步:經(jīng)過resultHandler處理過后,每行記錄會被映射成一個對象。該對象暫存在 這個Result上下文中。(暫存DefaultResultContext)
  DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
  ResultSet resultSet = rsw.getResultSet();
  // 跳過指定的偏移量,相當(dāng)于limit只不過他是內(nèi)存分頁,一般用不到(RowBounds中指定的偏移量)
  skipRows(resultSet, rowBounds);
  // 第二步:結(jié)果集中會有很多記錄,通過該循環(huán)處理結(jié)果集中的每條記錄。每個記錄最后都會存儲到ResultHandler的List集合中。
  while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
    // 處理discrimination標簽。類似于Java中的switch語法。如果resultMap標簽有鑒別器。則根據(jù)case的情況動態(tài)的獲取resultMap映射結(jié)果集
    ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
    // 第三步:獲取記錄映射的對象(重要?。。。。。。?
    Object rowValue = getRowValue(rsw, discriminatedResultMap, null);
    // 第四步:把對象存儲到上下文中。
    storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
  }
}

下面是該方法的執(zhí)行邏輯

第一步:定義ResultContext對象(前文說過),它用來暫存每一行記錄的處理結(jié)果的對象。從ResultSetWrapper中獲取JDBC的結(jié)果集對象ResultSet。skipRows方法跳過指定的內(nèi)存分頁(一般沒什么用,忽略該方法即可,研究價值不大)

第二步:遍歷結(jié)果集,通過resolveDiscriminatedResultMap方法得到鑒別器鑒別的ResultMap對象,其實本質(zhì)上還是一個ResultMap(有關(guān)鑒別器的內(nèi)容請參考另一篇文章:MyBatis discriminator標簽 實戰(zhàn)和原理解析

第三步:調(diào)用getRowValue方法處理每一行數(shù)據(jù)并得到結(jié)果對象

第四步:把上一步生成的對象通過上下文ResultContext添加到ResultHandler中。(再次提示:ResultHandler對象里面存放結(jié)果集解析后的對象集合哦)

其中,重點操作在第三步和第四步。接下來我們就先來聊聊getRowValue方法是如何處理一行記錄的。

getRowValue

private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
  final ResultLoaderMap lazyLoader = new ResultLoaderMap();
  // (重要方法?。。。。。。。。。。。。┍热绶祷亟Y(jié)果ResultType指定的是map,那么這里就會創(chuàng)建一個空Map對象,下面的if才是給map里添加元素。
  Object rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
  if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
    final MetaObject metaObject = configuration.newMetaObject(rowValue);
    boolean foundValues = this.useConstructorMappings;
    if (shouldApplyAutomaticMappings(resultMap, false)) {
      // (重要方法?。。。。。。。。。。。。┦欠駪?yīng)該自動映射。比如說SQL返回結(jié)果集有10列,但是resultMap只配置了9個字段,剩下的那個字段,如果滿足返回列與映射列名稱相同,就會自動進行映射
      foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
    }
    // (重要方法!?。。。。。。。。。。。┨幚韗esultMap標簽中的映射。把結(jié)果集根據(jù)resultMap中的映射關(guān)系生成最終的結(jié)果對象。屬性會被設(shè)置到metaObject中
    foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
    foundValues = lazyLoader.size() > 0 || foundValues;
    // isReturnInstanceForEmptyRow是否啟用。如果開啟則返回空對象,否則返回null。
    // 注:這個空對象依賴于createResultObject方法創(chuàng)建出的對象是空還是null。
    rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
  }
  return rowValue;
}

該方法處理邏輯如下(延時加載的代碼請忽略,簡單映射不會涉及到延時加載,這里之所以會出現(xiàn)ResultLoaderMap這樣延時加載相關(guān)的對象,是因為嵌套映射方法也會調(diào)用這個方法解析結(jié)果集。)

第一步:首先通過createResultObject對象創(chuàng)建一個空殼對象,啥是空殼對象呢?比如說xml文件中的resultMap標簽定義了返回值類型是User類型,那么這里就會創(chuàng)建一個User對象,但是屬性值全為空。

當(dāng)然createResultObject背后的邏輯其實很復(fù)雜,它會首先判斷用戶是否在resultMap標簽中定義了構(gòu)造器標簽,如果沒定義才會按上述流程描述所說的創(chuàng)建一個空殼對象。但如果用戶在resultMap標簽中定義了構(gòu)造器標簽,那么就會直接將結(jié)果集中的數(shù)據(jù)通過構(gòu)造器構(gòu)造出完整的對象。這樣也很能理解嗎,畢竟調(diào)用構(gòu)造器是要傳值的。

第二步:通過applyAutomaticMappings方法完成自動映射,啥是自動映射嘞。比如一條sql返回的列由name age兩列,但是resultMap標簽中只定義了一個映射關(guān)系name,那么age列就會自動尋找映射關(guān)系,如果發(fā)現(xiàn)列名age與resultMap返回類型的屬性同名,就會自動映射到該類型中。該步驟中只會映射resultMap標簽中未定義的映射關(guān)系對應(yīng)的字段

第三步:通過applyPropertyMappings方法完成屬性映射,它是第二步的補充,完成resultMap標簽中result標簽的映射關(guān)系

最后:返回解析完成的值

到此,結(jié)果集中的一條記錄已經(jīng)被解析用戶指定的類型對象了,接下來就是要把該對象返回給用戶,這就要回到我們上一步的storeObject方法了。接下來來看下DefaultResultSetHandler#storeObject方法

storeObject

private void storeObject(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue, ResultMapping parentMapping, ResultSet rs) throws SQLException {
  if (parentMapping != null) {
    // 處理ResultSets標簽時走這個分支
    linkToParents(rs, parentMapping, rowValue);
  } else {
    callResultHandler(resultHandler, resultContext, rowValue);
  }
}
private void callResultHandler(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue) {
  resultContext.nextResultObject(rowValue);
  ((ResultHandler<Object>) resultHandler).handleResult(resultContext);
}

storeObject方法的邏輯也很簡單(一般都會走到callResultHandler方法)

第一步:通過nextResultObject方法存儲getRowValue方法解析的結(jié)果對象。

第二步:把單行記錄的解析對象存入到ResultHandler的集合當(dāng)中

嵌套映射

簡單介紹完了簡單映射之后,接下來我們來看下比較復(fù)雜的嵌套映射,在嵌套映射中也會有很多問題,比如:循環(huán)依賴如何解決、延遲加載如何解決。 本節(jié)只針對于一般情況下的嵌套映射做出分析,循環(huán)依賴和延時加載后續(xù)我會繼續(xù)更新文章。

回想一下上一小節(jié)中提到的handleRowValues方法,它會根據(jù)ResultMap對象判斷是否是嵌套映射,如果是嵌套映射,就會走入handleRowValuesForNestedResultMap方法,接下來我們就來看下handleRowValuesForNestedResultMap這個方法。

handleRowValuesForNestedResultMap

private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
  // 第一步 獲取上下文對象,用于存儲單行處理后的記錄
  final DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
  ResultSet resultSet = rsw.getResultSet();
  skipRows(resultSet, rowBounds);
  Object rowValue = previousRowValue;
  // 第二步: 遍歷結(jié)果集
  while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
    final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
    // 嵌套映射中的結(jié)果都會被存入到nestedResultObjects中。這里的CacheKey就是緩存對象唯一標識
    final CacheKey rowKey = createRowKey(discriminatedResultMap, rsw, null);
    // 映射過程中的對象也會被存入在此。
    Object partialObject = nestedResultObjects.get(rowKey);
    // 通常會走到該分支。獲取一行記錄處理后的對象(有可能是半成品)
    rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject);
    if (partialObject == null) {
      storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
    }
  }
  if (rowValue != null && mappedStatement.isResultOrdered() && shouldProcessMoreRows(resultContext, rowBounds)) {
    storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
    previousRowValue = null;
  } else if (rowValue != null) {
    previousRowValue = rowValue;
  }
}

其實仔細閱讀這段可以發(fā)現(xiàn)它和簡單映射的代碼是有一部分雷同的,這也很好理解,嵌套映射還是基于簡單映射的思想進行遞歸處理結(jié)果集映射關(guān)系的嘛。接下來來介紹一下代碼的流程

第一步:還是獲取上下文對象,獲取JDBC的結(jié)果集對象。就不羅嗦了

第二步:遍歷結(jié)果集,處理每一行數(shù)據(jù)

第三步:創(chuàng)建CacheKey對象,使用嵌套映射中的外層對象創(chuàng)建緩存key,為了解決一對多映射

第四步:從緩存中通過CacheKey對象獲取外層對象。這里的nestedResultObjects是DefaultResultSetHandler的一個屬性,他就是用來緩存嵌套映射中的外層對象的。如果是第一次循環(huán),從緩存中獲取肯定是為空的嘛。但是你想一下這種場景——一個用戶(user)擁有多個訂單(order),這種一堆多的關(guān)系,在同一個用戶進行到循環(huán)的第二輪時,肯定不希望再創(chuàng)建一個外層對象,而是想讓order對象都公用一個外城對象。這種情況只能添加緩存來做了。這就是nestedResultObjects的意義。

這里的partialObject就是外層對象,也可以稱作是部分對象,因為它不完整嘛。

第五步:調(diào)用getRowValue方法獲取行記錄解析的結(jié)果

第六步:調(diào)用storeObject方法存儲對象到ResultHancler中

其中最重要的是要理解第四步中的嵌套思想,以及第五步解析一行記錄的詳細過程。這里一定會涉及到循環(huán)調(diào)用,因為解析外層對象必然要解析內(nèi)層對象嘛

getRowValue

private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, CacheKey combinedKey, String columnPrefix, Object partialObject) throws SQLException {
  final String resultMapId = resultMap.getId();
  Object rowValue = partialObject;
  // 映射第一次肯定一定為null
  if (rowValue != null) {
    final MetaObject metaObject = configuration.newMetaObject(rowValue);
    putAncestor(rowValue, resultMapId);
    applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, false);
    ancestorObjects.remove(resultMapId);
  } else {
    final ResultLoaderMap lazyLoader = new ResultLoaderMap();
    rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
    if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
      final MetaObject metaObject = configuration.newMetaObject(rowValue);
      boolean foundValues = this.useConstructorMappings;
      if (shouldApplyAutomaticMappings(resultMap, true)) {
        foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
      }
      foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
      putAncestor(rowValue, resultMapId);
      foundValues = applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, true) || foundValues;
      ancestorObjects.remove(resultMapId);
      foundValues = lazyLoader.size() > 0 || foundValues;
      rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
    }
    if (combinedKey != CacheKey.NULL_CACHE_KEY) {
      nestedResultObjects.put(combinedKey, rowValue);
    }
  }
  return rowValue;
}

映射時,第一次外層對象一定為null,所以會走else分支,只有在一堆多種的第二次映射才會走到if分支。我們來看下else分支的處理邏輯

第一步:首先通過createResultObject對象創(chuàng)建一個空殼對象,簡單映射中提過

第二步:通過applyAutomaticMappings方法完成自動映射

第三步:通過applyPropertyMappings方法完成屬性映射,它是第二步的補充,完成resultMap標簽中result標簽的映射關(guān)系

第四步:通過applyNestedResultMappings方法完成嵌套映射

到此,結(jié)果集中的一條記錄已經(jīng)被嵌套解析完成了。其中和簡單映射不一樣的地方只有多調(diào)用了一個applyNestedResultMappings方法,完成嵌套映射。我們來看下這個方法

applyNestedResultMappings

private boolean applyNestedResultMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String parentPrefix, CacheKey parentRowKey, boolean newObject) {
  boolean foundValues = false;
  for (ResultMapping resultMapping : resultMap.getPropertyResultMappings()) {
    final String nestedResultMapId = resultMapping.getNestedResultMapId();
    if (nestedResultMapId != null && resultMapping.getResultSet() == null) {
      // 獲取內(nèi)層對象
      rowValue = getRowValue(rsw, nestedResultMap, combinedKey, columnPrefix, rowValue);
      if (rowValue != null && !knownValue) {
        // 把內(nèi)層對象關(guān)聯(lián)到外層對象
        linkObjects(metaObject, resultMapping, rowValue);
        foundValues = true;
      }
    }
  }
  return foundValues;
}

它的執(zhí)行邏輯是遍歷resultMapping,對resultMapping進行g(shù)etRowValue方法的調(diào)用,此時就應(yīng)該屬于簡單影射了(除非嵌套了很多層)

它通過for循環(huán)每個resultMapping,直到找到嵌套映射的哪一個字段,然后再進行簡單映射封裝結(jié)果返回作為外層對象的屬性值。

它的調(diào)用邏輯是getRowValue——applyNestedResultMappings——getRowValue,直到嵌套映射完成位置,嵌套多少層,這個鏈路就會深多少層。

小結(jié)

mybatis解析結(jié)果集是通過遍歷結(jié)果集數(shù)據(jù),并把結(jié)果集數(shù)據(jù)對照resultMap標簽中的映射關(guān)系一一映射,如果存在嵌套映射則嵌套執(zhí)行g(shù)etRowValue獲取一行記錄的結(jié)果并關(guān)聯(lián)到外層對象。

以上就是MyBatis handleResultSet結(jié)果集解析過程示例的詳細內(nèi)容,更多關(guān)于MyBatis handleResultSet 的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot基于Disruptor實現(xiàn)高效的消息隊列?

    SpringBoot基于Disruptor實現(xiàn)高效的消息隊列?

    Disruptor是一個開源的Java框架,它被設(shè)計用于在生產(chǎn)者-消費者問題上獲得盡量高的吞吐量和盡量低的延遲,本文主要介紹了SpringBoot基于Disruptor實現(xiàn)高效的消息隊列?,具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • Springboot2.x結(jié)合Mabatis3.x下Hikari連接數(shù)據(jù)庫報超時錯誤

    Springboot2.x結(jié)合Mabatis3.x下Hikari連接數(shù)據(jù)庫報超時錯誤

    本文針對Springboot2.x與Mybatis3.x結(jié)合使用時,Hikari連接數(shù)據(jù)庫出現(xiàn)超時錯誤的問題進行了深入分析,并提供了一系列有效的解決方法,感興趣的可以了解一下
    2023-11-11
  • Java 面向?qū)ο蟮奶卣鹘馕雠c應(yīng)用

    Java 面向?qū)ο蟮奶卣鹘馕雠c應(yīng)用

    Java 是面向?qū)ο蟮木幊陶Z言,對象就是面向?qū)ο蟪绦蛟O(shè)計的核心。所謂對象就是真實世界中的實體,對象與實體是一一對應(yīng)的,也就是說現(xiàn)實世界中每一個實體都是一個對象,它是一種具體的概念
    2021-11-11
  • Spring主配置文件(applicationContext.xml) 導(dǎo)入約束詳解

    Spring主配置文件(applicationContext.xml) 導(dǎo)入約束詳解

    在本篇文章里我們給各位整理的是關(guān)于Spring主配置文件(applicationContext.xml) 導(dǎo)入約束的相關(guān)知識點內(nèi)容,需要參考下。
    2019-08-08
  • Java面試題沖刺第十五天--設(shè)計模式

    Java面試題沖刺第十五天--設(shè)計模式

    這篇文章主要為大家分享了最有價值的三道關(guān)于設(shè)計模式的面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 如何解決使用restTemplate進行feign調(diào)用new HttpEntity<>報錯問題

    如何解決使用restTemplate進行feign調(diào)用new HttpEntity<>報錯問題

    這篇文章主要介紹了如何解決使用restTemplate進行feign調(diào)用new HttpEntity<>報錯問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • Mybatis攔截器實現(xiàn)數(shù)據(jù)分表

    Mybatis攔截器實現(xiàn)數(shù)據(jù)分表

    當(dāng)數(shù)據(jù)量比較多時,放在一個表中的時候會影響查詢效率,本文主要介紹了Mybatis攔截器實現(xiàn)數(shù)據(jù)分表,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-01-01
  • java在hashmap初始化時賦初值過程解析

    java在hashmap初始化時賦初值過程解析

    這篇文章主要介紹了java在hashmap初始化時賦初值過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-10-10
  • MyBatis+MyBatisPlus中遇到的一些坑及解決

    MyBatis+MyBatisPlus中遇到的一些坑及解決

    這篇文章主要介紹了MyBatis+MyBatisPlus中遇到的一些坑及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 在java中用Scanner類讀入單個字符的方法

    在java中用Scanner類讀入單個字符的方法

    今天小編就為大家分享一篇在java中用Scanner類讀入單個字符的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07

最新評論

仁怀市| 明溪县| 昌江| 望城县| 富蕴县| 同德县| 黎川县| 乐都县| 印江| 建宁县| 乌苏市| 云南省| 那坡县| 厦门市| 都昌县| 诸城市| 盐池县| 盐源县| 喀什市| 铜鼓县| 丰原市| 巢湖市| 元谋县| 大安市| 乐平市| 屯昌县| 布拖县| 岳阳市| 清苑县| 金沙县| 新和县| 平昌县| 荆门市| 卫辉市| 林甸县| 江川县| 福贡县| 西和县| 陕西省| 洮南市| 登封市|