欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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,如下:
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方法。
-----------------------------------------
文笔不好,欢迎留言,忘老鸟指正。