成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

mybatis結(jié)果的組裝

antz / 1992人閱讀

摘要:系列集成的的解析與加載如何根據(jù)接口生成其實(shí)現(xiàn)類(lèi)的返回結(jié)果集結(jié)果的組裝序本文主要解答一個(gè)問(wèn)題,即如果沒(méi)有,而且屬性不是的,的自動(dòng)組裝是否可以賦值成功的問(wèn)題。備注本文的代碼引用來(lái)自的版本的源碼

mybatis系列

SpringBoot集成mybatis

mybatis的statement的解析與加載

mybatis如何根據(jù)mapper接口生成其實(shí)現(xiàn)類(lèi)

mybatis的mapper返回map結(jié)果集

mybatis結(jié)果的組裝

本文主要解答一個(gè)問(wèn)題,即如果bean沒(méi)有setter,而且屬性不是public的,mybatis的自動(dòng)組裝是否可以賦值成功的問(wèn)題。

查詢(xún)調(diào)用過(guò)程

DefaultSqlSession.selectList -->SimpleExecutor.doQuery --> SimpleStatementHandler.query --> DefaultResultSetHandler.handleResultSets --> BeanWrapper.setBeanProperty --> MetaClass.getSetInvoker --> Reflector.getSetInvoker

關(guān)鍵方法 SimpleStatementHandler.query
public  List query(Statement statement, ResultHandler resultHandler) throws SQLException {
    String sql = boundSql.getSql();
    statement.execute(sql);
    return resultSetHandler.handleResultSets(statement);
  }
DefaultResultSetHandler.handleResultSets
@Override
  public List handleResultSets(Statement stmt) throws SQLException {
    ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
 
    final List multipleResults = new ArrayList();
 
    int resultSetCount = 0;
    ResultSetWrapper rsw = getFirstResultSet(stmt);
 
    List 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.getResulSets();
    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);
  }
DefaultResultSetHandler.handleResultSets
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List multipleResults, ResultMapping parentMapping) throws SQLException {
    try {
      if (parentMapping != null) {
        handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
      } else {
        if (resultHandler == null) {
          DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
          handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
          multipleResults.add(defaultResultHandler.getResultList());
        } else {
          handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
        }
      }
    } finally {
      // issue #228 (close resultsets)
      closeResultSet(rsw.getResultSet());
    }
  }
DefaultResultSetHandler.handleRowValues
private void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler 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);
    }
  }
DefaultResultSetHandler.handleRowValuesForSimpleResultMap
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
      throws SQLException {
    DefaultResultContext resultContext = new DefaultResultContext();
    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());
    }
  }
DefaultResultSetHandler.getRowValue
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
    final ResultLoaderMap lazyLoader = new ResultLoaderMap();
    Object resultObject = createResultObject(rsw, resultMap, lazyLoader, null);
    if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
      final MetaObject metaObject = configuration.newMetaObject(resultObject);
      boolean foundValues = !resultMap.getConstructorResultMappings().isEmpty();
      if (shouldApplyAutomaticMappings(resultMap, false)) {
        foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;
      }
      foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;
      foundValues = lazyLoader.size() > 0 || foundValues;
      resultObject = foundValues ? resultObject : null;
      return resultObject;
    }
    return resultObject;
  }
DefaultResultSetHandler.applyPropertyMappings
private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix)
      throws SQLException {
    final List mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);
    boolean foundValues = false;
    final List propertyMappings = resultMap.getPropertyResultMappings();
    for (ResultMapping propertyMapping : propertyMappings) {
      String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
      if (propertyMapping.getNestedResultMapId() != null) {
        // the user added a column attribute to a nested result map, ignore it
        column = null;
      }
      if (propertyMapping.isCompositeResult()
          || (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH)))
          || propertyMapping.getResultSet() != null) {
        Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix);
        // issue #541 make property optional
        final String property = propertyMapping.getProperty();
        // issue #377, call setter on nulls
        if (value != DEFERED
            && property != null
            && (value != null || (configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive()))) {
          metaObject.setValue(property, value);
        }
        if (value != null || value == DEFERED) {
          foundValues = true;
        }
      }
    }
    return foundValues;
  }
MetaObject.setValue
public void setValue(String name, Object value) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
      if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
        if (value == null && prop.getChildren() != null) {
          // don"t instantiate child path if value is null
          return;
        } else {
          metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);
        }
      }
      metaValue.setValue(prop.getChildren(), value);
    } else {
      objectWrapper.set(prop, value);
    }
  }
BeanWrapper.set
@Override
  public void set(PropertyTokenizer prop, Object value) {
    if (prop.getIndex() != null) {
      Object collection = resolveCollection(prop, object);
      setCollectionValue(prop, collection, value);
    } else {
      setBeanProperty(prop, object, value);
    }
  }
BeanWrapper.setBeanProperty
private void setBeanProperty(PropertyTokenizer prop, Object object, Object value) {
    try {
      Invoker method = metaClass.getSetInvoker(prop.getName());
      Object[] params = {value};
      try {
        method.invoke(object, params);
      } catch (Throwable t) {
        throw ExceptionUtil.unwrapThrowable(t);
      }
    } catch (Throwable t) {
      throw new ReflectionException("Could not set property "" + prop.getName() + "" of "" + object.getClass() + "" with value "" + value + "" Cause: " + t.toString(), t);
    }
  }
MetaClass.getSetInovker
public Invoker getSetInvoker(String name) {
    return reflector.getSetInvoker(name);
  }
Reflector.getSetInvoker
public Invoker getSetInvoker(String propertyName) {
    Invoker method = setMethods.get(propertyName);
    if (method == null) {
      throw new ReflectionException("There is no setter for property named "" + propertyName + "" in "" + type + """);
    }
    return method;
  }
setMethods的修改 有setter的話,走Reflector. resolveSetterConflicts
private void resolveSetterConflicts(Map> conflictingSetters) {
    for (String propName : conflictingSetters.keySet()) {
      List setters = conflictingSetters.get(propName);
      Method firstMethod = setters.get(0);
      if (setters.size() == 1) {
        addSetMethod(propName, firstMethod);
      } else {
        Class expectedType = getTypes.get(propName);
        if (expectedType == null) {
          throw new ReflectionException("Illegal overloaded setter method with ambiguous type for property "
              + propName + " in class " + firstMethod.getDeclaringClass() + ".  This breaks the JavaBeans " +
              "specification and can cause unpredicatble results.");
        } else {
          Iterator methods = setters.iterator();
          Method setter = null;
          while (methods.hasNext()) {
            Method method = methods.next();
            if (method.getParameterTypes().length == 1
                && expectedType.equals(method.getParameterTypes()[0])) {
              setter = method;
              break;
            }
          }
          if (setter == null) {
            throw new ReflectionException("Illegal overloaded setter method with ambiguous type for property "
                + propName + " in class " + firstMethod.getDeclaringClass() + ".  This breaks the JavaBeans " +
                "specification and can cause unpredicatble results.");
          }
          addSetMethod(propName, setter);
        }
      }
    }
  }

private void addSetMethod(String name, Method method) {
    if (isValidPropertyName(name)) {
      setMethods.put(name, new MethodInvoker(method));
      setTypes.put(name, method.getParameterTypes()[0]);
    }
  }
沒(méi)有setter的話,走Reflector. addSetField
private void addSetField(Field field) {
    if (isValidPropertyName(field.getName())) {
      setMethods.put(field.getName(), new SetFieldInvoker(field));
      setTypes.put(field.getName(), field.getType());
    }
  }
小結(jié)

即使bean的屬性是私有的,沒(méi)有setter,mybatis也會(huì)通過(guò)反射去設(shè)置值。

備注

本文的代碼引用來(lái)自mybatis的3.3.0版本的源碼

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/65630.html

相關(guān)文章

  • 介紹 mybatis 執(zhí)行 SQL 大致過(guò)程

    摘要:本文通過(guò)方法來(lái)用執(zhí)行帶參數(shù)的命令,來(lái)介紹執(zhí)行的大致過(guò)程。三是返回值的類(lèi)型。返回值的類(lèi)型包括兩部分,一是返回結(jié)果本身的類(lèi)型,二是返回結(jié)果的每個(gè)字段各是什么類(lèi)型用于轉(zhuǎn)換。對(duì)象是一個(gè)很復(fù)雜的對(duì)象,涵蓋了執(zhí)行命令需要的所有東西。 本文通過(guò) main() 方法來(lái)用 mybatis 執(zhí)行帶參數(shù)的 SQL 命令,來(lái)介紹 mybatis 執(zhí)行 SQL 的大致過(guò)程。 準(zhǔn)備數(shù)據(jù)庫(kù) 準(zhǔn)備一個(gè) MySQL 數(shù)...

    derek_334892 評(píng)論0 收藏0
  • mybatis使用奇技淫巧

    摘要:那么查詢(xún)結(jié)果應(yīng)該為張三服裝茶具李四服裝服裝此處需要注意一點(diǎn),的元素調(diào)用方法時(shí),自動(dòng)映射的屬性名和列名應(yīng)該保持一致,或者列表必須是數(shù)據(jù)庫(kù)表中的字段名,而不是別名。 合并多行查詢(xún)的結(jié)果 業(yè)務(wù)需求 商家可以根據(jù)商品類(lèi)目分類(lèi),每位商家可以有多個(gè)商品類(lèi)目,商品類(lèi)目又跟運(yùn)營(yíng)類(lèi)目有一種關(guān)聯(lián)規(guī)則。此處暫且不說(shuō)運(yùn)營(yíng)類(lèi)目。根據(jù)業(yè)務(wù),商家信息是一張表,商家與商品類(lèi)目有一張關(guān)聯(lián)表,商品類(lèi)目有一張表,權(quán)且使用三...

    alexnevsky 評(píng)論0 收藏0
  • 【深入淺出MyBatis筆記】MyBatis解析和運(yùn)行原理

    摘要:的解析和運(yùn)行原理構(gòu)建過(guò)程提供創(chuàng)建的核心接口。在構(gòu)造器初始化時(shí)會(huì)根據(jù)和的方法解析為命令。數(shù)據(jù)庫(kù)會(huì)話器定義了一個(gè)對(duì)象的適配器,它是一個(gè)接口對(duì)象,構(gòu)造器根據(jù)配置來(lái)適配對(duì)應(yīng)的對(duì)象。它的作用是給實(shí)現(xiàn)類(lèi)對(duì)象的使用提供一個(gè)統(tǒng)一簡(jiǎn)易的使用適配器。 MyBatis的解析和運(yùn)行原理 構(gòu)建SqlSessionFactory過(guò)程 SqlSessionFactory提供創(chuàng)建MyBatis的核心接口SqlSess...

    bitkylin 評(píng)論0 收藏0
  • Mybatis使用小札

    摘要:你數(shù)據(jù)庫(kù)的默認(rèn)值不起作用而是得到,那怎么解決這個(gè)問(wèn)題呢通過(guò)使用和標(biāo)簽我們解決了這個(gè)問(wèn)題。將和均交由該處理,但本人實(shí)測(cè),這個(gè)好像并沒(méi)有什么卵用,有用的是在文件中顯式指定,如下所示。 前言 Mybatis在我所見(jiàn)過(guò)的持久化框架里真心是一個(gè)異類(lèi),因?yàn)樗莝ql-centric的,而不是基于對(duì)象和表映射的。我會(huì)在本文中講一下Mybatis幾個(gè)重要的技巧,與本文的上一篇文章Hibernate做...

    SegmentFault 評(píng)論0 收藏0
  • mybatis參數(shù)格式化異常:NumberFormatException: For input st

    摘要:此類(lèi)問(wèn)題,在配置中,做的比較好,所以,官方也不是很放心其注解,建議使用。錯(cuò)誤的引起,是和引起的,原因給的是字符串,卻拿一個(gè)數(shù)字比較,會(huì)做一些轉(zhuǎn)化,結(jié)果在數(shù)字格式化時(shí)發(fā)生異常。 使用mybatis注解開(kāi)發(fā)的時(shí)候,總會(huì)遇到很多問(wèn)題,但是mybatis的注解并不是那么的美好,一些問(wèn)題或者錯(cuò)誤根本不能給出準(zhǔn)確的定位,有時(shí)候,甚至?xí)o出Unknow Source的錯(cuò)誤,獲取就是一個(gè)關(guān)閉標(biāo)簽沒(méi)有關(guān)...

    aaron 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<