您好,登錄后才能下訂單哦!
本篇內容介紹了“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進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。