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。

mybatis ResultHandler vs ResultSetHandler及自定义扩展的更多相关文章

  1. SpringBoot(十一):springboot2.0.2下配置mybatis generator环境,并自定义字段/getter/settetr注释

    Mybatis Generator是供开发者在mybatis开发时,快速构建mapper xml,mapper类,model类的一个插件工具.它相对来说对开发者是有很大的帮助的,但是它也有不足之处,比 ...

  2. SharePoint 2013 自定义扩展菜单

    在对SharePoint进行开发或者功能扩展的时候,经常需要对一些默认的菜单进行扩展,以使我们开发的东西更适合SharePoint本身的样式.SharePoint的各种功能菜单,像网站设置.Ribbo ...

  3. SharePoint 2013 自定义扩展菜单(二)

    接博文<SharePoint 2013 自定义扩展菜单>,多加了几个例子,方便大家理解. 例七 列表设置菜单扩展(listedit.aspx) 扩展效果 XML描述 <CustomA ...

  4. WCF自定义扩展,以实现aop!

    引用地址:https://msdn.microsoft.com/zh-cn/magazine/cc163302.aspx  使用自定义行为扩展 WCF Aaron Skonnard 代码下载位置: S ...

  5. Jquery自定义扩展方法(二)--HTML日历控件

    一.概述 研究了上节的Jquery自定义扩展方法,自己一直想做用jquery写一个小的插件,工作中也用到了用JQuery的日历插件,自己琢磨着去造个轮子--HTML5手机网页日历控件,废话不多说,先看 ...

  6. Silverlight实例教程 - 自定义扩展Validation类,验证框架的总结和建议(转载)

    Silverlight 4 Validation验证实例系列 Silverlight实例教程 - Validation数据验证开篇 Silverlight实例教程 - Validation数据验证基础 ...

  7. jQuery 自定义扩展,与$冲突处理

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. SparkContext自定义扩展textFiles,支持从多个目录中输入文本文件

    需求   SparkContext自定义扩展textFiles,支持从多个目录中输入文本文件   扩展   class SparkContext(pyspark.SparkContext): def ...

  9. 基于 HtmlHelper 的自定义扩展Container

    基于 HtmlHelper 的自定义扩展Container Intro 基于 asp.net mvc 的权限控制系统的一部分,适用于对UI层数据呈现的控制,基于 HtmlHelper 的扩展组件 Co ...

随机推荐

  1. 升级.net core 3.x 后mvc项目调试状态编辑view代码不能实时预览

    https://stackoverflow.com/a/58126955 简单来说 需要在nuget上安装Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilati ...

  2. linux常见依赖

    1. 搭建LNMP环境用到的依赖包 yum -y install gcc gcc-c++ libxml2 libxml2-devel openssl openssl-devel curl libcur ...

  3. git远程上的分支到本地

    先想一个自己要在本地新建的分支名称,qianjinyan git checkout -b qianjinyan origin/SELLER-2248-1018 git branch 查看分支 git ...

  4. windows + SQL Server环境,创建ArcSDE服务

    ArcGIS for Server启用FeatureService需要ArcSDE和Geodatabase. 使用ArcSDE需要创建windows服务,ArcSDE只有命令行,所以只好阅读文档,找合 ...

  5. 闲谈关于discuz内核缓存机制

    Discuz! 缓存 Discuz! X2.5 的 config_global.php 中有这样一行代码 $_config['cache']['type'] = 'sql'; 这就是 Discuz! ...

  6. 20180606模拟赛T1——猫鼠游戏

    题目描述: 猫和老鼠在10*10的方格中运动,例如: *...*..... ......*... ...*...*.. .......... ...*.C.... *.....*... ...*... ...

  7. redux的知名ppt

    https://slides.com/jenyaterpil/redux-from-twitter-hype-to-production#/20

  8. tf.placeholder函数说明

    函数形式: tf.placeholder(     dtype,     shape=None,     name=None ) 参数: dtype:数据类型.常用的是tf.float32,tf.fl ...

  9. python - django 设置自定义文件保存路径

    一. settings.py MEDIA_URL = "/qir/" # 设置获取文件时的访问根路径 MEDIA_ROOT = os.path.join(BASE_DIR, &qu ...

  10. Openwrt build env setup(9)

    reference : https://openwrt.org/docs/guide-developer/quickstart-build-images Install dependence pack ...