您好,登录后才能下订单哦!
本篇内容介绍了“Mybatis中ResultSetHandler的用法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
mybatis-3.4.6.release.
ResultSetHandler是个接口,如List-1
List-1
public interface ResultSetHandler { //将结果转换为List <E> List<E> handleResultSets(Statement stmt) throws SQLException; //将结果转换为游标Cursor <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException; void handleOutputParameters(CallableStatement cs) throws SQLException; }
实现类只有DefaultResultSetHandler,实现有点复杂,因为要考虑的情况很多。
结果封装原理
List-2
<resultMap type="Person" id="resultPersonMap"> <result property="id" column="id"/> <result property="username" column="username"/> <result property="password" column="password"/> <result property="fltNum" column="flt_num"/> </resultMap>
如List-2, 定义这样一个ResultMap后,使用ObjectFactory创建一个Person对象,
person.setId(resultSet.getInt("id"))
person.setUsername(resultSet.getString("username"))
person.setPassword(resultSet.getString("password"))
person.setFltNum(resultSet.getString("flt_num"))
不过这个转换过程在实现上很复杂,其中就用到TypeHandler。
开始之前,来看下ResultSetWrapper,如下List-3,通过ResultSet获取ResultSetMetaData来获取列的属性,遍历列,获取列名称、列类型、对应的JdbcType。
List-3
public ResultSetWrapper(ResultSet rs, Configuration configuration) throws SQLException { super(); this.typeHandlerRegistry = configuration.getTypeHandlerRegistry(); this.resultSet = rs; final ResultSetMetaData metaData = rs.getMetaData(); final int columnCount = metaData.getColumnCount(); for (int i = 1; i <= columnCount; i++) { columnNames.add(configuration.isUseColumnLabel() ? metaData.getColumnLabel(i) : metaData.getColumnName(i)); jdbcTypes.add(JdbcType.forCode(metaData.getColumnType(i))); classNames.add(metaData.getColumnClassName(i)); } }
来看DefaultResultSetHandler的handleResultSets方法,
List-4
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);//1 List<ResultMap> resultMaps = mappedStatement.getResultMaps();//2 int resultMapCount = resultMaps.size(); validateResultMapsCount(rsw, resultMapCount);//3 while (rsw != null && resultMapCount > resultSetCount) { ResultMap resultMap = resultMaps.get(resultSetCount);//4 handleResultSet(rsw, resultMap, multipleResults, null);//5 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); }
1处通过ResultSetMetadata获取列的属性
2处获取我们定义的resultMap,如List-2
3处验证resultMap个数,如果小于1则会报错
4处获取resultMap,从List中
5处是核心,调用handleResultSet->handleRowValues->handleRowValuesForSimpleResultMap
List-5
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);//1 storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet()); } }
handleRowValuesForSimpleResultMap方法中,不断调用resultSet.next()方法,会获取resultSet中的所有数据。
List-5的1处,调用getRowValue方法,该方法获取resultSet中的一行数据,并将数据封装位对象
List-6
private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException { final ResultLoaderMap lazyLoader = new ResultLoaderMap(); Object rowValue = createResultObject(rsw, resultMap, lazyLoader, null);//1 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;//2 } foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues; foundValues = lazyLoader.size() > 0 || foundValues; rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null; } return rowValue; }
List-6中1处,通过反射,创建Person对象(如List-7),之后在List-6的2处
List-7
<select id="findByUsername" resultType="Person" parameterType="Person"> select * from person where username=#{username}; </select>
List-8
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; }
List-8中,createAutomaticMappings方法返还sql查询的列属性——从ResultSetWrapper中获取的,之后遍历这些列,对每一列,都调用typeHandler.getResult方法获取值,之后用metaObject.setValue,内部通过反射的方式设置值。这样createAutomaticMappings方法执行完成后,就获取了resultSet中的一行数据,且封装到对象中了。
回到List-5中,getRowValue方法返回值,storeObject方法中将值放入到List中。
描述较为泛华,建议个人阅读源码。此外,比如懒加载在ResultSetHandler中实现。
https://github.com/mybatis/mybatis-3/tree/3.4.x
“Mybatis中ResultSetHandler的用法”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。