java mybatis关于plugin讲解
程序员文章站
2022-04-30 18:21:42
...
这段时间不怎么忙,又回过头来想了想mybatis分页的情况。在网上看了几位师兄的博客,回过头自己又整理了一下。大家都是知道了,mybatis可以通过自定义插件实现分页功能,很多博客中都说过了,这是拦截器的形式。既然是拦截器实现的分页,那么拦截器拦截的是什么呢?拦截以后我们应该做什么呢?搞懂这两个问题就明白这个分页的拦截器是怎么回事儿了。其实拦截器不仅仅这点作用。进入正题。
mybatis官网中说明了,mybatis plugin可以拦截四个类系的对象:Executor,ParameterHandler, ResultSetHandler ,StatementHandler ;而我们要拦截的无非也就是Dao中的方法。不要急往下读
Executor:这个相当于就是mybatis调用jdbc的执行器,这里的功能就多了,大致包含查询、更新,提交事务,回滚等等;
ParameterHandler:这个相当于是专门处理被拦截方法中的参数,比如要将拦截的方法的参数中加一个值、或是验证一下什么的、或是修一下值;
ResultSetHandler :这个就简单了寒,很明显就是拦截方法返回的结果,对结果集进行再加工;
StatementHandler :这个一个是不是很熟悉,JDBC和它就相关了。分页就可以使用它也来处理了,获得原来的sql,再进行处理加工成分页的sql,最终就可以实现。
-------------------------------------
我们回过头来看看,定义一个拦截器,当然是实现mybatis的Interceptor,如下:
-----------------------------------------
通过以上说明,大家应该发现一点,就是DAO方法被拦截后,会先加载xml中的属性配置,也就是先执行setProperties这个方法,然后对这四个类型的实例对象进行包装,也就是执行plugin方法(注解配置谁,就包装谁,并返回代理对象,未包装的直接返回原对象),最后执行intercept方法,完成具体的执行。
------------------------------------------
最后总结一下就是:通过xml的plugin配置,拦截对应的DAO方法;然后在自定义拦截器中,配置注释,我们具体要做的事(是加工SQL、是处理结果集、是处理参数、还是处理执行器,以及他们对应的方法和参数);明确后,就是调用到wrap方法了,对具体的对象进行包装,并返回;最后执行intercept方法。
-----------------------------------------
文笔不好,欢迎留言,忘老鸟指正。
mybatis官网中说明了,mybatis plugin可以拦截四个类系的对象:Executor,ParameterHandler, ResultSetHandler ,StatementHandler ;而我们要拦截的无非也就是Dao中的方法。不要急往下读
Executor:这个相当于就是mybatis调用jdbc的执行器,这里的功能就多了,大致包含查询、更新,提交事务,回滚等等;
ParameterHandler:这个相当于是专门处理被拦截方法中的参数,比如要将拦截的方法的参数中加一个值、或是验证一下什么的、或是修一下值;
ResultSetHandler :这个就简单了寒,很明显就是拦截方法返回的结果,对结果集进行再加工;
StatementHandler :这个一个是不是很熟悉,JDBC和它就相关了。分页就可以使用它也来处理了,获得原来的sql,再进行处理加工成分页的sql,最终就可以实现。
-------------------------------------
我们回过头来看看,定义一个拦截器,当然是实现mybatis的Interceptor,如下:
public class PageInterceptor implements Interceptor {,这里要实现他的三个方法,分别是
@Intercepts({ @Signature(args = { Connection.class }, method = "prepare", type = StatementHandler.class) }) public class PageInterceptor implements Interceptor { /* * 这个方法很很明显就是算是,拦截器要做什么的地方,大家看到invocation这个就应该熟悉了, * 反射,不多说。通过反射就可以获取到目标对象,参数,和方法名。注意这里的方法名不是dao的中方法名。 方法中的代码很简单了吧。 */ public Object intercept(Invocation invocation) throws Throwable { StatementHandler statement = (StatementHandler) invocation.getTarget(); BoundSql boundSql = statement.getBoundSql(); Object parameterObject = boundSql.getParameterObject(); //此处的parameterObject为被拦截DAO方法的参数,比如这个Dao的参数可以为一个page对象,对象属性包含当前面,每页显示的行数,总页数,总行数,当前页的结果集(一般为一个List),以及一个集合(前端传递过来的,查询条件集合) System.err.println(parameterObject); String sql = boundSql.getSql(); //这里获得原来sql后,就可以进行改造了,处理为查询总数据的即可。 System.err.println(sql); Connection connectin = (Connection) invocation.getArgs()[0]; //此处获取到的就是prepare方法。 return invocation.proceed(); } /* * 这里多说一下,这是就是包装前面所说的mybait提供中的四个类系对象,这个方法会被执行四次。具体被包装的是哪个看具体的配置。当前被包装就是StatementHandler类系的对象(类的注解上面标识出来了),没有被包装的对象,原样返回,被装的就返回代理对象。 */ public Object plugin(Object target) { return Plugin.wrap(target, this); } /*这个方法就是获取外部xml中配置property的key,如下 <plugins> <plugin interceptor="com.liuhao.stu.PageInterceptor"> <property name="dialect" value="mysql" /> <property name="pageSqlId" value=".*ListPage.*" /> </plugin> </plugins> 这里有一点很重要,就是<plugins>这组标签在配置拦截器时,要放到最前面,不然XML报错,很无解。这个属性配置就很有用了哈,比如当前拦截的是什么数据库,就可以通过这里来区分了;拦截什么样了DAO方法也可以在这里实现了,比如以ListPage、paging,page结尾的。当拦截的就是包含ListPage的DAO方法都会被拦截 */ public void setProperties(Properties p) { String dialect = p.getProperty("dialect"); String pageSqlId = p.getProperty("pageSqlId"); } }
-----------------------------------------
通过以上说明,大家应该发现一点,就是DAO方法被拦截后,会先加载xml中的属性配置,也就是先执行setProperties这个方法,然后对这四个类型的实例对象进行包装,也就是执行plugin方法(注解配置谁,就包装谁,并返回代理对象,未包装的直接返回原对象),最后执行intercept方法,完成具体的执行。
------------------------------------------
最后总结一下就是:通过xml的plugin配置,拦截对应的DAO方法;然后在自定义拦截器中,配置注释,我们具体要做的事(是加工SQL、是处理结果集、是处理参数、还是处理执行器,以及他们对应的方法和参数);明确后,就是调用到wrap方法了,对具体的对象进行包装,并返回;最后执行intercept方法。
-----------------------------------------
文笔不好,欢迎留言,忘老鸟指正。