文主要解答一个问题,即如果bean没有setter,而且属性不是public的,mybatis的自动组装是否可以赋值成功的问题。

查询调用过程

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

关键方法

SimpleStatementHandler.query

public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException { String sql = boundSql.getSql(); statement.execute(sql); return resultSetHandler.<E>handleResultSets(statement); }

DefaultResultSetHandler.handleResultSets

@Overridepublic 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.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<Object> 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<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()); } }

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<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix); boolean foundValues = false; final List<ResultMapping> 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

@Overridepublic 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<String, List<Method>> conflictingSetters) { for (String propName : conflictingSetters.keySet()) { List<Method> 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<Method> 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]); } }

没有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()); } }

小结

即使bean的属性是私有的,没有setter,mybatis也会通过反射去设置值。

转载于:https://www.cnblogs.com/austinspark-jessylu/p/8065355.html

mybatis结果的组装(springboot)相关推荐

  1. mybatis generator生成example_[Springboot系列] SpringBoot与Mybatis结合

    本文作者:cuifuan Mybatis 是一个持久层ORM框架,负责Java与数据库数据交互,也可以简易理解为中介,相对于它,还有个中介是hibernate,不过在mybatis中sql语句的灵活性 ...

  2. oracle和mybatis自增,在Springboot项目中使用MybatisPlus和Oracle实现主键ID的自增

    在Springboot项目中使用MybatisPlus和Oracle实现主键ID的自增 发布时间:2020-11-18 15:49:35 来源:亿速云 阅读:125 作者:Leah 在Springbo ...

  3. MyBatis凭什么征服SpringBoot ?

    1.MyBatis的优势 众所周知,MyBatis 是一款优秀的持久层框架,它支持自定义 SQL.存储过程以及高级映射.通过xml映射到接口,使开发者使用接口的方式就能够轻松的映射.解析.执行xml中 ...

  4. mybatis和mybatis-plus集成springboot的配置区别

    将mybatis更改为mybatis-plus时,除了需要在pom.xml文件中修改依赖以外,还需要在application.yml文件中修改配置信息. 1. 添加mybatis-plus依赖 < ...

  5. springboot 引入jdbc驱动_SpringBoot整合jdbc、durid、mybatis详解,数据库的连接就是这么简单...

    SpringBoot底层统一采用SpringData处理数据库,这一章主要来讲一下SpringBoot整合jdbc.durid.mybatis的方式. (一)整合jdbc 整合jdbc主要有三步: 1 ...

  6. springboot+mybatis+SpringSecurity 实现用户角色数据库管理(一)

    本文使用springboot+mybatis+SpringSecurity 实现用户权限数据库管理 实现用户和角色用数据库存储,而资源(url)和权限的对应采用硬编码配置. 也就是角色可以访问的权限通 ...

  7. SpringBoot整合Mybatis超详细流程

    SpringBoot整合Mybatis超详细流程 文章目录 SpringBoot整合Mybatis超详细流程 前言 详细流程 0.引入Mybatis 1.创建数据 2.创建程序目录 3.理解后台访问流 ...

  8. SpringBoot整合Mybatis(高级)

    SpringBoot整合Mybatis(高级) 文章目录 SpringBoot整合Mybatis(高级) 前言 基础环境配置 增删改查 ResultMap 复杂查询 多对一 一对多 动态SQL if ...

  9. 玩转springboot:整合mybatis实例

    这篇文章讲解一下springboot整合mybatis,其实,springboot整合mybatis和springmvc整合mybatis并没有什么太大的区别,大体上还是差不多哦,只是比springm ...

  10. (一)SpringBoot 整合 MyBatis

    一.工具 IDE:idea.DB:mysql 二.创建SpringBoot工程 在Idea中使用SpringInitializr模板创建SpringBoot工程,依赖选择如下: 这里也可以不选JDBC ...

最新文章

  1. Python 获取list 中指定元素出现的次数
  2. 区块链死亡项目列表小程序:死亡硬币
  3. 中國批准英特爾在東北投建晶片廠
  4. python连接spark_python如何通过pyspark的API操作spark
  5. Android-DataBinding源码探究
  6. JavaScript语言基础(二)
  7. IT众包Web网站服务案例:江苏保税店
  8. Java讲课笔记14:final关键字
  9. 【零基础学Java】—抽象方法和抽象类(二十二)
  10. 心心念念的安卓简单和多功能计算器来了
  11. 关于MAC的pkg和mpkg的分别
  12. django商城项目之历史浏览记录
  13. Canvas递归画一棵树
  14. Chrome浏览器数据本地备份
  15. 机器学习 识别图片人物动作_一键学习人物识别说明
  16. tidyverse笔记——tidyr包
  17. Leetcode DAY6: 有效的字母异位词 and 两个数组的交集 and 快乐数 and 两数之和
  18. DIY制作高精度低温漂电阻箱0.1~9.9GΩ(1)-- 项目介绍
  19. 录制失败因为媒体服务失败_杨丽萍62岁被判人生失败,因为她一生无子女.........
  20. echarts实用篇(一)——饼状图

热门文章

  1. 第十一次课:Python函数(二)
  2. CentOS7忘记root密码的解决方法
  3. HTML5离线存储 初探
  4. Android 一步步教你从ActionBar迁移到ToolBar
  5. LINUX信息命令查看大全
  6. 理解Java的几张图
  7. plsql创建、测试存储过程
  8. 离职 Oracle 首席工程师怒喷:MySQL 是“超烂的数据库”,建议考虑 PostgreSQL
  9. 全网最全 Java 日志框架适配方案!还有谁不会?
  10. 老程序员被裁员,面试半年未果,同行:都四十了还是码农,怪谁?