摘要:系列集成的的解析與加載如何根據接口生成其實現類的返回結果集結果的組裝序本文主要解答一個問題,即如果沒有,而且屬性不是的,的自動組裝是否可以賦值成功的問題。備注本文的代碼引用來自的版本的源碼
mybatis系列
SpringBoot集成mybatis
mybatis的statement的解析與加載
mybatis如何根據mapper接口生成其實現類
mybatis的mapper返回map結果集
mybatis結果的組裝
序本文主要解答一個問題,即如果bean沒有setter,而且屬性不是public的,mybatis的自動組裝是否可以賦值成功的問題。
查詢調用過程DefaultSqlSession.selectList -->SimpleExecutor.doQuery --> SimpleStatementHandler.query --> DefaultResultSetHandler.handleResultSets --> BeanWrapper.setBeanProperty --> MetaClass.getSetInvoker --> Reflector.getSetInvoker
關鍵方法 SimpleStatementHandler.querypublicDefaultResultSetHandler.handleResultSetsList query(Statement statement, ResultHandler resultHandler) throws SQLException { String sql = boundSql.getSql(); statement.execute(sql); return resultSetHandler. handleResultSets(statement); }
@Override public ListDefaultResultSetHandler.handleResultSets
private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, ListDefaultResultSetHandler.handleRowValuesmultipleResults, 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()); } }
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 { DefaultResultContextDefaultResultSetHandler.getRowValueresultContext = 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()); } }
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 ListMetaObject.setValuemappedColumnNames = 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; }
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沒有setter的話,走Reflector. addSetField> 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]); } }
private void addSetField(Field field) { if (isValidPropertyName(field.getName())) { setMethods.put(field.getName(), new SetFieldInvoker(field)); setTypes.put(field.getName(), field.getType()); } }小結
即使bean的屬性是私有的,沒有setter,mybatis也會通過反射去設置值。
備注本文的代碼引用來自mybatis的3.3.0版本的源碼
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/65630.html
摘要:本文通過方法來用執行帶參數的命令,來介紹執行的大致過程。三是返回值的類型。返回值的類型包括兩部分,一是返回結果本身的類型,二是返回結果的每個字段各是什么類型用于轉換。對象是一個很復雜的對象,涵蓋了執行命令需要的所有東西。 本文通過 main() 方法來用 mybatis 執行帶參數的 SQL 命令,來介紹 mybatis 執行 SQL 的大致過程。 準備數據庫 準備一個 MySQL 數...
摘要:那么查詢結果應該為張三服裝茶具李四服裝服裝此處需要注意一點,的元素調用方法時,自動映射的屬性名和列名應該保持一致,或者列表必須是數據庫表中的字段名,而不是別名。 合并多行查詢的結果 業務需求 商家可以根據商品類目分類,每位商家可以有多個商品類目,商品類目又跟運營類目有一種關聯規則。此處暫且不說運營類目。根據業務,商家信息是一張表,商家與商品類目有一張關聯表,商品類目有一張表,權且使用三...
摘要:的解析和運行原理構建過程提供創建的核心接口。在構造器初始化時會根據和的方法解析為命令。數據庫會話器定義了一個對象的適配器,它是一個接口對象,構造器根據配置來適配對應的對象。它的作用是給實現類對象的使用提供一個統一簡易的使用適配器。 MyBatis的解析和運行原理 構建SqlSessionFactory過程 SqlSessionFactory提供創建MyBatis的核心接口SqlSess...
摘要:你數據庫的默認值不起作用而是得到,那怎么解決這個問題呢通過使用和標簽我們解決了這個問題。將和均交由該處理,但本人實測,這個好像并沒有什么卵用,有用的是在文件中顯式指定,如下所示。 前言 Mybatis在我所見過的持久化框架里真心是一個異類,因為它是sql-centric的,而不是基于對象和表映射的。我會在本文中講一下Mybatis幾個重要的技巧,與本文的上一篇文章Hibernate做...
摘要:此類問題,在配置中,做的比較好,所以,官方也不是很放心其注解,建議使用。錯誤的引起,是和引起的,原因給的是字符串,卻拿一個數字比較,會做一些轉化,結果在數字格式化時發生異常。 使用mybatis注解開發的時候,總會遇到很多問題,但是mybatis的注解并不是那么的美好,一些問題或者錯誤根本不能給出準確的定位,有時候,甚至會給出Unknow Source的錯誤,獲取就是一個關閉標簽沒有關...
閱讀 2473·2021-11-24 09:39
閱讀 3406·2021-11-15 11:37
閱讀 2251·2021-10-08 10:04
閱讀 3965·2021-09-09 11:54
閱讀 1883·2021-08-18 10:24
閱讀 1033·2019-08-30 11:02
閱讀 1793·2019-08-29 18:45
閱讀 1651·2019-08-29 16:33