亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

基于mybatis-plus timestamp返回為null問題的排除

 更新時間:2021年08月31日 11:58:39   作者:水中加點糖  
這篇文章主要介紹了mybatis-plus timestamp返回為null問題的排除,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

問題是這樣的

在開發(fā)時,為了節(jié)約時間,我選擇了mybatis框架來開發(fā),然后又在網(wǎng)上找了一個許多人都推薦的mybatis-plus來作為持久層框架。

于是乎我按照官方的DEMO下了一個springBoot的mybatis-plus版本的DEMO

這個DEMO是基于H2數(shù)據(jù)庫的,跑了下沒有問題。DEMO是能正常運行的。

然后我將這個工程的代碼快速拷貝的新的一個工程里,并把數(shù)據(jù)庫由H2換為了MYSQL。但項目跑起來時,出現(xiàn)了如下問題:

數(shù)據(jù)庫里的數(shù)據(jù)如下圖

表結(jié)構(gòu)如下圖

查詢出來的結(jié)果中對于timestamp類型的字段為空

為了解決這個問題,我決定通過debug斷點觀察下是否查詢是把數(shù)據(jù)數(shù)據(jù)查出來了

由于用的mybatis-plus框架來開發(fā),而mybaits-plus框架是基于mybatis框架的,為了看是否把數(shù)據(jù)查詢出來,直接在ResultSetHandler上把一個dubug就好。在默認情況下,mybatis框架使用的ResultSetHandler為DefaultResultSetHandler,當查詢mybatis查詢完畢后,會通過ResultSetHandler的handleResultSets(Statement stmt)方法對查詢的數(shù)據(jù)結(jié)果集進行封裝

所以將斷點打在handlerResultSets方法上最為合適。

再通過statement -> wrapper ->results -> rowData ->rows觀察發(fā)現(xiàn)如下數(shù)據(jù):

查詢返回的結(jié)果集中rows的記錄數(shù)為1,第1個字段的ascii為49,而49是ascii中數(shù)字1的值。而第二個字段也有值,說明所對應(yīng)的timestamp字段是有返回值的,數(shù)據(jù)庫查詢是沒有問題的。

然而通過mybatis代碼進一步封裝后的數(shù)據(jù)multipleResults又表示,只查詢到了類型為Int的字段的數(shù)據(jù)

這么也就是說,問題應(yīng)該是出在了multipleResults的賦值問題上了

handleResultSets的完整代碼為

//
// HANDLE RESULT SETS
//
@Override
public List<Object> handleResultSets(Statement stmt) throws SQLException {
  ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
  final List<Object> multipleResults = new ArrayList<Object>();
  int resultSetCount = 0;
  ResultSetWrapper rsw = getFirstResultSet(stmt);
  List<ResultMap> resultMaps = mappedStatement.getResultMaps();
  int resultMapCount = resultMaps.size();
  validateResultMapsCount(rsw, resultMapCount);
  while (rsw != null && resultMapCount > resultSetCount) {
    ResultMap resultMap = resultMaps.get(resultSetCount);
    handleResultSet(rsw, resultMap, multipleResults, null);
    rsw = getNextResultSet(stmt);
    cleanUpAfterHandlingResultSet();
    resultSetCount++;
  }
  String[] resultSets = mappedStatement.getResultSets();
  if (resultSets != null) {
    while (rsw != null && resultSetCount < resultSets.length) {
      ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
      if (parentMapping != null) {
        String nestedResultMapId = parentMapping.getNestedResultMapId();
        ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
        handleResultSet(rsw, resultMap, null, parentMapping);
      }
      rsw = getNextResultSet(stmt);
      cleanUpAfterHandlingResultSet();
      resultSetCount++;
    }
  }
  return collapseSingleResultList(multipleResults);
}

說明問題出在 handleResultSet(rsw, resultMap, multipleResults, null);這句代碼上了

通過代碼跟蹤,發(fā)現(xiàn)如下代碼

//
// GET VALUE FROM ROW FOR SIMPLE RESULT MAP
//
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;
}

繼而發(fā)現(xiàn)如下的核心代碼

private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
  List<UnMappedColumnAutoMapping> autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);
  boolean foundValues = false;
  if (!autoMapping.isEmpty()) {
    for (UnMappedColumnAutoMapping mapping : autoMapping) {
      final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);
      if (value != null) {
        foundValues = true;
      }
      if (value != null || (configuration.isCallSettersOnNulls() && !mapping.primitive)) {
        // gcode issue #377, call setter on nulls (value is not 'found')
        metaObject.setValue(mapping.property, value);
      }
    }
  }
  return foundValues;
}

通過斷點發(fā)現(xiàn)以下數(shù)據(jù)

在獲取這個查詢的的返回字段時,只獲取出來兩個,即int類型和varchar類型的.

再通過跟蹤發(fā)現(xiàn)了如下代碼

private List<UnMappedColumnAutoMapping> createAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
  final String mapKey = resultMap.getId() + ":" + columnPrefix;
  List<UnMappedColumnAutoMapping> autoMapping = autoMappingsCache.get(mapKey);
  if (autoMapping == null) {
    autoMapping = new ArrayList<UnMappedColumnAutoMapping>();
    final List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);
    for (String columnName : unmappedColumnNames) {
      String propertyName = columnName;
      if (columnPrefix != null && !columnPrefix.isEmpty()) {
        // When columnPrefix is specified,
        // ignore columns without the prefix.
        if (columnName.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) {
          propertyName = columnName.substring(columnPrefix.length());
        } else {
          continue;
        }
      }
      final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase());
      if (property != null && metaObject.hasSetter(property)) {
        if (resultMap.getMappedProperties().contains(property)) {
          continue;
        }
        final Class<?> propertyType = metaObject.getSetterType(property);
        if (typeHandlerRegistry.hasTypeHandler(propertyType, rsw.getJdbcType(columnName))) {
          final TypeHandler<?> typeHandler = rsw.getTypeHandler(propertyType, columnName);
          autoMapping.add(new UnMappedColumnAutoMapping(columnName, property, typeHandler, propertyType.isPrimitive()));
        } else {
          configuration.getAutoMappingUnknownColumnBehavior()
              .doAction(mappedStatement, columnName, property, propertyType);
        }
      } else {
        configuration.getAutoMappingUnknownColumnBehavior()
            .doAction(mappedStatement, columnName, (property != null) ? property : propertyName, null);
      }
    }
    autoMappingsCache.put(mapKey, autoMapping);
  }
  return autoMapping;
}

直到看到這里

final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase()); 

才知道問題所在了, configuration.isMapUnderscoreToCamelCase()的值為true,即開啟了駝峰命令。

所以查找字段時就找不到。 把之前的類似crt_time改為crtTime后,就可以了! 沒想到這么一個小錯誤,讓我糾結(jié)了這么久!還好能跟蹤源碼!

通過這次的問題排查,讓我明白了一個道理: 如果不知道某個框架原理的情況下,不要隨便填寫它的配置信息。在享受到框架的便捷性的同時,最好也得要明白它的原理,這樣當出現(xiàn)問題時,才好快速定位。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java實現(xiàn)計網(wǎng)循環(huán)冗余檢驗算法的方法示例

    Java實現(xiàn)計網(wǎng)循環(huán)冗余檢驗算法的方法示例

    這篇文章主要給大家介紹了關(guān)于Java實現(xiàn)計網(wǎng)循環(huán)冗余檢驗算法的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • Java使用jdbc連接實現(xiàn)對MySQL增刪改查操作的全過程

    Java使用jdbc連接實現(xiàn)對MySQL增刪改查操作的全過程

    JDBC的全稱是Java?Database?Connectivity,即Java數(shù)據(jù)庫連接,它是一種可以執(zhí)行SQL語句的Java?API,下面這篇文章主要給大家介紹了關(guān)于Java使用jdbc連接實現(xiàn)對MySQL增刪改查操作的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • Java 實戰(zhàn)項目錘煉之樸素風格個人博客系統(tǒng)的實現(xiàn)流程

    Java 實戰(zhàn)項目錘煉之樸素風格個人博客系統(tǒng)的實現(xiàn)流程

    讀萬卷書不如行萬里路,只學書上的理論是遠遠不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用Java+vue+Springboot+ssm+mysql+maven+redis實現(xiàn)一個樸素風格的個人博客系統(tǒng),大家可以在過程中查缺補漏,提升水平
    2021-11-11
  • Java Testcontainers庫實現(xiàn)測試功能

    Java Testcontainers庫實現(xiàn)測試功能

    這篇文章主要介紹了Java Testcontainers庫實現(xiàn)測試功能,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • SpringBoot Security整合JWT授權(quán)RestAPI的實現(xiàn)

    SpringBoot Security整合JWT授權(quán)RestAPI的實現(xiàn)

    這篇文章主要介紹了SpringBoot Security整合JWT授權(quán)RestAPI的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-11-11
  • 一文帶你搞懂Java單例模式

    一文帶你搞懂Java單例模式

    單例就是單實例的意思,即在系統(tǒng)全局,一個類只創(chuàng)建一個對象,并且在系統(tǒng)全局都可以訪問這個對象而不用重新創(chuàng)建。本文將通過示例為大家詳細講解Java單例模式的使用,需要的可以參考一下
    2022-11-11
  • spring的pointcut正則表達式的實現(xiàn)

    spring的pointcut正則表達式的實現(xiàn)

    本文主要介紹了spring的pointcut正則表達式的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • SpringRunner和SpringJUnit4ClassRunner的區(qū)別及說明

    SpringRunner和SpringJUnit4ClassRunner的區(qū)別及說明

    這篇文章主要介紹了SpringRunner和SpringJUnit4ClassRunner的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • JAVA annotation入門基礎(chǔ)

    JAVA annotation入門基礎(chǔ)

    以下是JAVA annotation入門基礎(chǔ),新手朋友們可以過來參考下。希望對你有所幫助
    2013-08-08
  • Java GUI編程實現(xiàn)在線聊天室

    Java GUI編程實現(xiàn)在線聊天室

    這篇文章主要為大家詳細介紹了Java GUI編程實現(xiàn)在線聊天室,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07

最新評論