首页 > 作文

Springboot自定义mybatis拦截器实现扩展

更新时间:2023-04-04 09:17:12 阅读: 评论:0

前言

相信大家对拦截器并不陌生,对mybatis也不陌生。

有用过pagehelper的,那么对mybatis拦截器也不陌生了,按照使用的规则触发sql拦截,帮我们自动添加分页参数 。

那么今天,我们的实践 自定义mybatis拦截器也是如此, 本篇文章实践的效果:

针对一些使用 单个实体类去接收返回结果的 mapper方法,我们拦截检测,如果没写 limit 1 ,我们将自动帮忙填充,达到查找单条数据 效率优化的效果。

ps: 当然,跟着该篇学会了这个之后,那么可以扩展的东西就多了,大家按照自己的想法或是项目需求都可以自己发挥。 我该篇的实践仅仅作为抛砖引玉吧。

正文

实践的准备 :

整合mybatis ,然后故意写了3个查询方法, 1个是list 列表数据,2个是 单条数据 。

高考几天时间考完我们通过自己写一个mybatisinterceptor实现 mybatis框架的interceptor来做文章:

mybatisinterceptor.java :

import org.apache.ibatis.executor.executor;import org.apache.ibatis.mapping.*;import org.apache.ibatis.plugin.*;import org.apache.ibatis.ssion.resulthandler;import org.apache.ibatis.ssion.rowbounds;import org.springframework.stereotype.component; import java.lang.reflect.method;import java.util.*;   /** * @author jcccc * @description * @date 2021/12/14 16:56 */@component@intercepts({        @signature(type = executor.class, method = "update", args = {mappedstatement.class, object.class}),        @signature(type = executor.class, method = "query", args = {mappedstatement.class, object.class, rowbounds.class, resulthandler.class})})public class mybatisinterceptor implements interceptor {     @override    public object intercept(invocation invocation) throws throwable {        //获取执行参数        object[] objects = invocation.getargs();        mappedstatement ms = (mappedstatement) objects[0];        //解析执行sql唐诗三百首幼儿早教朗诵的map方法,开始自定义规则匹配逻辑        string mappermethodallname = ms.getid();        int lastindex = mappermethodallname.lastindexof(".");        string mapperclassstr = mappermethodallname.substring(0, lastindex);        string mapperclassmethodstr = mappermethodallname.substring((lastindex + 1));        class<?> mapperclass = class.forname(mapperclassstr);        method[] methods = mapperclass.getmethods();        class<?> returntype;        for (method method : methods) {            if (method.getname().equals(mapperclassmethodstr)) {                returntype = method.getreturntype();                if (returntype.isassignablefrom(list.class)) {                    system.out.println("返回类型是 list");                    system.out.println("针对list 做一些操作");                } el if (returntype.isassignablefrom(t.class)) {                    system.out.println("返回类型是 t");                    system.out.println("针对t 做一些操作");                } el{                    boundsql boundsql = ms.getsqlsource().getboundsql(objects[1]);                    string oldsql = boundsql.getsql().tolowerca(locale.china).replace("[\\t\\n\\r]", " ");                    if (!oldsql.contains("limit")){                        string newsql = boundsql.getsql().tolowerca(locale.china).replace("[\\t\\n\\r]", " ") + " limit 1";                        boundsql newboundsql = new boundsql(ms.getconfiguration(), newsql,                                boundsql.getparametermappings(), boundsql.getparameterobject());                        mappedstatement newms = newmappedstatement(ms, new myboundsqlsqlsource(newboundsql));                        for (parametermapping mapping : boundsql.getparametermappings()) {                            string prop = mapping.getproperty();                            if (boundsql.hasadditionalparameter(prop)) {                                newboundsql.tadditionalparameter(prop, boundsql.getadditionalparameter(prop));                            }                        }                        object[] queryargs = invocation.getargs();                        queryargs[0] = newms;                        system.out.println("打印新sql语句" + newsql);                    }                 }            }        }        //继续执行逻辑        return invocation.proceed();    }      @override    public object plugin(object o) {        //获取代理权        if (o instanceof executor) {            //如果是executor(执行增删改查操作),则拦截下来            return plugin.wrap(o, this);        } el {            return o;        }    }     /**     * 定义一个内部辅助类,作用是包装 sql     */    class myboundsqlsqlsource implements sqlsource {        private boundsql boundsql;         public myboundsqlsqlsource(boundsql boundsql) {            this.boundsql = boundsql;        }         @override        public boundsql getboundsql(object parameterobject) {            return boundsql;        }     }     private mappedstatement newmappedstatement(mappedstatement ms, sqlsource newsqlsource) {        mappedstatement.builder builder = new                mappedstatement.builder(ms.getconfiguration(), ms.getid(), newsqlsource, ms.getsqlcommandtype());        builder.resource(ms.getresource());        builder.fetchsize(ms.getfetchsize());        builder.statementtype(ms.getstatementtype());        builder.keygenerator(ms.getkeygenerator());        if (ms.getkeyproperties() != null && ms.getkeyproperties().length > 0) {            builder.keyproperty(ms.getkeyproperties()[0]);        }        builder.timeout(ms.gettimeout());        builder.parametermap(ms.getparametermap());        builder.resultmaps(ms.getresultmaps());        builder.resultttype(ms.getresultttype());        builder.cache(ms.getcache());        builder.flushcacherequired(ms.isflushcacherequired());        builder.ucache(ms.isucache());        return builder.build();    }      @override    public void tproperties(properties properties) {        //读取mybatis配置文件中属性    }  }

简单代码端解析:

① 拿出执行参数,里面有很多东西给我们用的,我本篇主要是用mappedstatement。大家可以发挥自己的想法。 打debug可以自己看看里面的东西。

//获取执行参数object[] objects = invocation.getargs();mappedstatement ms = (mappedstatement) objects[0];

② 这里我主要是使用了从mappedstatement里面拿出来的id,做切割分别切出来 目前执行的sql的mapper是哪个,然后方法是哪个。

string mappermethodallname = ms.getid();int lastindex = mappermethodallname.lastindexof(".");string mapperclassstr = mappermethodallname.substring(多媒体教学的优点0, lastindex);string mapperclassmethodstr = mappermethodallname.substring((lastindex + 1));

③ 这就是我自己随便写的一下,我直接根据切割出来的mapper类找出里面的方法,主要是为了拿出每个方法的返回类型,因为 我这篇实践内容就是,判断出单个pojo接受的mapper方法,加个limit 1 , 其他的 list 、t 、 page 等等这些,我暂时不做扩展。

class<?> mapperclass = class.forname(mapperclassstr);method[] methods = mapperclass.getmethods();class<?> returntype;

④这一段代码就是该篇的拓展逻辑了,从mappedstatement里面拿出 sqlsource,然后再拿出boundsql,然后一顿操作 给加上limit 1 , 然后new 一个新的mappedstatement,一顿操作塞回去invocation 里面

boundsql boundsql = ms.getsqlsource().getboundsql(objects[1]);string oldsql = boundsql.getsql().tolowerca(locale.china).replace("[\\t\\n\\r]", " ");if (!oldsql.contains("limit")){    str炒股心得ing newsql = boundsql.getsql().tolowerca(locale.china).replace("[\\t\\n\\r]", " ") + " limit 1";    boundsql newboundsql = new boundsql(ms.getconfiguration(), newsql,            boundsql.getparametermappings(), boundsql.getparameterobject());    mappedstatement newms = newmappedstatement(m感恩母亲的作文200字s, new myboundsqlsqlsource(newboundsql));    for (parametermapping mapping : boundsql.getparametermappings()) {        string prop = mapping.getproperty();        if (boundsql.hasadditionalparameter(prop)) {            newboundsql.tadditionalparameter(prop, boundsql.getadditionalparameter(prop));        }    }    object[] queryargs = invocation.getargs();    queryargs[0] = newms;    system.out.println("打印新sql语句:" + newsql);}

ok,最后简单来试试效果 :

最后再重申一下,本篇文章内容只是一个抛砖引玉,随便想的一些实践效果,大家可以按照自己的想法发挥。

最后再补充一个 解决 mybatis自定义拦截器和pagehelper 拦截器 冲突导致失效的问题出现的

解决方案:

加上一个拦截器配置类

mydatasourceinterceptorconfig.java :

import org.apache.ibatis.ssion.sqlssionfactory;import org.springframework.beans.factory.annotation.autowired;import org.springframework.context.applicationlistener;import org.springframework.context.event.contextrefreshedevent;import org.springframework.stereotype.component; import java.util.list; /** * @author jcccc * @description * @date 2021/12/14 16:56 */@componentpublic class mydatasourceinterceptorconfig implements applicationlistener<contextrefreshedevent> {     @autowired    private mybatisinterceptor mybatisinterceptor;     @autowired    private list<sqlssionfactory> sqlssionfactories;     @override    public void onapplicationevent(contextrefreshedevent contextrefreshedevent) {        for (sqlssionfactory factory : sqlssionfactories) {            factory.getconfiguration().addinterceptor(mybatisinterceptor);        }    }}

最后最后再补充多一些,

文中 针对拦截的是executor 这种接口的插件,

其实 还可以使用parameterhandler、resultthandler、statementhandler。

每当执行这四种接口对象的方法时,就会进入拦截方法,然后我们可以根据不同的插件去拿不同的参数。

类似:

@signature(method = "prepare", type = statementhandler.class, args = {connection.class,integer.class})

然后可以做个转换,也是可以取出相关的 boundsql 等等 :

if (!(invocation.gettarget() instanceof routingstatementhandler)){                return invocation.proceed();            }            routingstatementhandler statementhandler = (routingstatementhandler) invocation.gettarget();            boundsql boundsql = statementhandler.getboundsql();            string sql = boundsql.getsql().toupperca();

parameterhandler、resultthandler、statementhandler、executor ,不同的插件拦截,有不同的使用场景,想深入的看客们,可以深一下。

到此这篇关于springboot自定义mybatis拦截器实现扩展的文章就介绍到这了,更多相关springboot mybatis拦截器内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!

本文发布于:2023-04-04 09:17:10,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/0a7e76f580bda02e18729a681f55b8e3.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:Springboot自定义mybatis拦截器实现扩展.doc

本文 PDF 下载地址:Springboot自定义mybatis拦截器实现扩展.pdf

标签:方法   拦截器   自己的   自定义
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图