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的高级结果集映射

1    一对一查询 案例:查询所有订单信息,关联查询下单用户信息。   注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信...
  • hsl_1990_08_15
  • hsl_1990_08_15
  • 2016年06月27日 11:05
  • 802

Mybatis结果集自动映射

Mybatis结果集自动映射          在使用Mybatis时,有的时候我们可以不用定义resultMap,而是直接在语句上指定resultType。这个时候其实就用到了Mybatis的结...
  • u010643307
  • u010643307
  • 2017年04月12日 23:06
  • 2033

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

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

关于Mybatis中动态查询表和表中的列

STATEMENT" resultType="long"> SELECT COUNT(*) FROM ${tableName} WHERE ${busiCodeName} = ${busiCodeV...
  • Smile___you
  • Smile___you
  • 2016年09月01日 18:30
  • 2073

MyBATIS中的插件原理和应用

如果你不懂反射和动态代理请参考我的博文:http://blog.csdn.net/ykzhen2015/article/details/50312651 这是本文的基础,请先掌握它,否则下面内容的将...
  • ykzhen2015
  • ykzhen2015
  • 2015年12月18日 09:28
  • 7369

mybits对于数据库返回的结果集为动态时用JSONObjst接收方法

mybits对于数据库返回的结果集为动态时用JSONObjst接收方法 如下:       esultType="com.alibaba.fastjson.JSO...
  • builderwfy
  • builderwfy
  • 2016年12月24日 14:25
  • 206

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

动态查询
  • qq_20261343
  • qq_20261343
  • 2016年02月16日 20:31
  • 7740

【MyBatis】myBatis动态传入表名、字段名(列名)进行查询

由于分表就涉及到了有相近查询语句只是表名不同的情况,刚开始使用了 select from TABLENAME = #{openId,jdbcType...
  • tanglei6636
  • tanglei6636
  • 2016年08月01日 11:00
  • 14860

深入了解MyBatis返回值

深入了解MyBatis返回值想了解返回值,我们需要了解resultType,resultMap以及接口方法中定义的返回值。我们先看resultType和resultMapresultType和resu...
  • isea533
  • isea533
  • 2015年06月10日 17:07
  • 98332

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

输出映射 接下来说说有关Mapper.xml配置文件中查询标签中关于返回值类型resultType与resultMap的一些内容 1.resultType 使用resultType进行输出映射,只有...
  • u013517797
  • u013517797
  • 2015年06月15日 23:07
  • 12111
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:MyBatis 返回动态结果类型插件
举报原因:
原因补充:

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