MyBatis 返回动态结果类型插件

原创 2016年10月16日 18:41:29

MyBatis 返回动态结果类型插件

说明

虽然写了这么一个插件,但是个人建议尽可能不去这么用,如果这个插件真正能方便你,使用起来也没任何问题。

关于插件的一些个人修改建议,在插件的注释中有说明。

插件用途:可以在 MyBatis 参数中带上要返回的类型Class,插件就会改变返回值类型为你指定的类型。

用法

说的可能不清楚,看个简单的用法。

MyBatis 中定义如下方法:

Object selectById(@Param("id")Long id, @Param("resultType")Class resultType);

//或

Object selectById(@Param("id")Long id, @Param("resultType")String resultType);

支持直接的Class或者String类型的全限定类名,必须指定参数的keyresultType,通过拦截器参数可以修改这个值,参数的顺序无所谓。

用法:

City city = (City) mapper.selectById(1L, City.class);

//或

City city = (City) mapper.selectById(1L, "tk.mybatis.model.City");

更变态直观的例子就是SQL也是动态传入${sql}这样方式的,不同SQL配不同的结果类型更能说明问题。你可以结合这篇 MyBatis 执行动态 SQL 博客使用。

如果看到这里觉得有用,你就可以继续往下看实现原理。

源码地址

http://git.oschina.net/free/Mybatis_Utils/tree/master/ResultType

虽然在git上,但我并不会长期维护这个插件。

实现原理

前面写过一篇 MyBatis Excutor 拦截器的巧妙用法,这个插件算是一个“修改MappedStatement 时解决并发的问题”可以参考复制的例子。

从上往下开始说实现。

拦截器签名:

@Intercepts(@Signature(
        type = Executor.class,
        method = "query",
        args = {
            MappedStatement.class, 
            Object.class, 
            RowBounds.class, 
            ResultHandler.class
        }
    )
)
public class ResultTypeInterceptor implements Interceptor {

拦截的Executor 的查询方法,拦截Executor的好处是自由度更高,但是难度也比其他的高,如果能够避免并发问题,实现起来会更容易。

拦截器处理代码

@Override
public Object intercept(Invocation invocation) throws Throwable {
    final Object[] args = invocation.getArgs();
    MappedStatement ms = (MappedStatement) args[0];
    Object parameterObject = args[1];
    //获取参数中设置的返回值类型
    Class resultType = getResultType(parameterObject);
    if(resultType == null){
        return invocation.proceed();
    }
    //复制ms,重设类型
    args[0] = newMappedStatement(ms, resultType);
    return invocation.proceed();
}

首先通过invocation.getArgs()可以得到当前执行方法的参数,这个参数列表和签名中定义的args中的类型是一致的。

其中第一个是(MappedStatement) args[0],第二个是参数对象parameterObject

首先要做的就是从参数对象中获得通过参数传递进来的resultType,使用 getResultType 方法获取。对参数不了解的人可能不清楚这里的参数可能是什么样,如果你想了解,可以看 深入了解MyBatis参数, 或者只是参考这个方法了解如何在这里处理参数。

得到返回值类型后,就该根据新的类型去创建一个resultMap,然后用这个新的类型根据现有的MappedStatement去创建一个新的MappedStatement,之所以创建一个新的而不是直接修改MappedStatement就是为了避免并发问题。

使用 newMappedStatement 创建新的MappedStatement对象,这个方法很重要,如果你要对MappedStatement做其他的修改,参考这个方法就可以。

通过下面代码就可以替换原有的ms :

args[0] = newMappedStatement(ms, resultType);

因为后续方式是使用参数(args)中的这个 ms,而不是 MyBatis Configuration中全局的ms,所以这里就避免了修改全局ms引起并发的问题。

虽然少数人能看到这里,但是我仍然建议,只学这段代码中的用法,尽可能不要去使用这个插件实现返回动态结果类型。直接使用会很不直观。但是呢,如果你是在开发一些通用框架方法,可以尝试在内部这么使用。

版权声明:版权归博主所有,转载请带上本文链接!联系方式:abel533@gmail.com

相关文章推荐

MyBatis动态SQL之动态返回列(Dynamic Column)

一,业务描述 最近单位有这样一个报表,根据选择的年份返回年份的列,比如,选择 城市,2015,2016年,那么返回列就是三列,城市,2015年数据,2016年数据,如果是只返回城市 , 2016年数据...

【Mybatis框架】输出映射-resultType与resultMap

输出映射 接下来说说有关Mapper.xml配置文件中查询标签中关于返回值类型resultType与resultMap的一些内容 1.resultType 使用resultType进行输出映射,只有...

mybatis resultType返回类型汇总。

1.返回List> 1 2 select id="getMyCredit"  parameterClass="java.util.Map" resultClass="j...
  • baicp3
  • baicp3
  • 2016年01月13日 10:02
  • 32545

Mybatis中的resultType和resultMap

一、概述 MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的,而resultMap则是对外部R...

Mybatis - 高级映射 (复习,数据表分析,一对一 之 resultType )

1.复习         MyBatis是一个持久层框架,mybatis是不完全的ORM框架。Sql语句需要程序员自己编写,但是Mybatris也有映射(输入映射和输出映射); MyBatis入门门槛...

Mybatis结果集自动映射

Mybatis结果集自动映射          在使用Mybatis时,有的时候我们可以不用定义resultMap,而是直接在语句上指定resultType。这个时候其实就用到了Mybatis的结...

mybatis--day01动态查询、动态更新、动态删除、动态插入

动态查询

MyBatis的返回参数类型

MyBatis的返回参数类型分两种 1. 对应的分类为: 1.1.resultMap: 1.2.resultType: 2 .对应返回值类型: 2.1.resultMap:结果集...

Mybatis最入门---ResultMaps高级用法(上)

接上文,我们基本的单表查询使用上文中的方式已经能够达到目的。但是,我们日常的业务中也存在着多表关联查询,结果是复杂的数据集合等等。本文我们就来介绍ResultMaps的高级用法,本文,我们先介绍基本的...
  • qi49125
  • qi49125
  • 2016年08月22日 15:53
  • 767

MyBatis学习笔记(五)输入(parameterType)与输出(resultType、resultMap)映射

转载自:输入(parameterType)与输出(resultType、resultMap)映射在MyBatis中,我们通过parameterType完成输入映射(指将值映射到sql语句的占位符中,值...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:MyBatis 返回动态结果类型插件
举报原因:
原因补充:

(最多只允许输入30个字)