mybatis ResultHandler vs ResultSetHandler及自定義擴展


ResultSetHandler是mybatis的關鍵類之一,用於對jdbc返回的ResultSet進行映射處理,其中包括列前綴處理,邏輯分頁,鑒別器(Discriminator,基於值實現動態映射列)處理等等。

ResultSetHandler在StatementHandler執行過程中構建,如下:

 

接下去來看ResultSetHandler的定義。最主要的是handleResultSets,它負責普通查詢結果的處理。

public interface ResultSetHandler {
    <E> List<E> handleResultSets(Statement var1) throws SQLException;

    <E> Cursor<E> handleCursorResultSets(Statement var1) throws SQLException;

    void handleOutputParameters(CallableStatement var1) throws SQLException;
}
handleResultSets在StatementHandler執行完成后被調用,如下:

 要對結果集自定義處理的話,可以改動此處源碼。因為mybatis攔截器支持對四大對象(Executor,StatementHandler,ParameterHandler,ResultSetHandler)都支持,所以也可以通過攔截器(參見mybatis自定義插件開發詳解)實現,各有利弊,LZ采用后者。

邏輯分頁也是在handleResultSets中處理。邏輯分頁由org.apache.ibatis.session.RowBounds實現,mybatis內置的應用層邏輯分頁實現定義,但基本上很少使用,定義如下。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.apache.ibatis.session;

public class RowBounds {
    public static final int NO_ROW_OFFSET = 0;
    public static final int NO_ROW_LIMIT = 2147483647;
    public static final RowBounds DEFAULT = new RowBounds();
    private final int offset;
    private final int limit;

    public RowBounds() {
        this.offset = 0;
        this.limit = 2147483647;
    }

    public RowBounds(int offset, int limit) {
        this.offset = offset;
        this.limit = limit;
    }

    public int getOffset() {
        return this.offset;
    }

    public int getLimit() {
        return this.limit;
    }
}

默認值為不分頁。在shouldProcessMoreRows中判斷,如下:

    private boolean shouldProcessMoreRows(ResultContext<?> context, RowBounds rowBounds) throws SQLException {
        return !context.isStopped() && context.getResultCount() < rowBounds.getLimit();
    }

 在處理每一行記錄的時候,先處理沒有明確映射(無或不在ResultMap中)的屬性,然后處理明確映射,如下:

    private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
        ResultLoaderMap lazyLoader = new ResultLoaderMap();
// 創建目標類型對象,如Pojo或Map Object rowValue
= this.createResultObject(rsw, resultMap, lazyLoader, (String)null); if (rowValue != null && !this.hasTypeHandlerForResultObject(rsw, resultMap.getType())) { MetaObject metaObject = this.configuration.newMetaObject(rowValue); boolean foundValues = this.useConstructorMappings; if (this.shouldApplyAutomaticMappings(resultMap, false)) { // map就是在這里自動映射的 foundValues = this.applyAutomaticMappings(rsw, resultMap, metaObject, (String)null) || foundValues; } foundValues = this.applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, (String)null) || foundValues; foundValues = lazyLoader.size() > 0 || foundValues; rowValue = !foundValues && !this.configuration.isReturnInstanceForEmptyRow() ? null : rowValue; } return rowValue; }

 接下去再來看ResultHandler,它用來對每行記錄映射或處理,典型的比如二次過濾或脫敏處理,都可以在這里處理,當然也可以通過插件,只不過在這里處理從性能上看最佳。其定義比較簡單:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.apache.ibatis.session;

public interface ResultHandler<T> {
    void handleResult(ResultContext<? extends T> var1);
}

 相對來說,ResultHandler的實現很簡單,這里就不詳解了,真的想了解的可以參考https://www.cnblogs.com/51life/p/9633002.html。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM