Mybatis学习- 拦截器-实现分页

本文的程序基本上都不是我自己实现的,网上有好多现成的例子。我只是根据自己理解,对整个过程进行了说明。


        Mybatis采用责任链模式,通过动态代理组织多个拦截器(插件),通过这些拦截器可以改变Mybatis的默认行为(诸如SQL重写之类的),由于插件会深入到Mybatis的核心,因此在编写自己的插件前最好了解下它的原理,以便写出安全高效的插件。Mybatis支持对Executor、StatementHandler、PameterHandler和ResultSetHandler进行拦截,也就是说会对这4种对象进行代理。

        对于分页,通过Mybatis学习- 拦截器-基本的图中,可以看到比较适合在StatementHandler上进行拦截。这样,我们通过获得其boundsql对象(就是sql语句+查询参数 的对象);然后判断boundsql对象的参数中有没有分页信息,如果有,则把分页信息取出来,然后重新组织boundsql的sql语句(因为,分页信息是动态的,所以对于mybatis来说这部分的参数mybatis处理不了,所以我们要取出来,然后根据这些信息去修改boundsql中的sql部分)。

好了,根据上面的思路,首先我们要获得StatementHandler:

if (ivk.getTarget() instanceof RoutingStatementHandler) {
			RoutingStatementHandler statementHandler = (RoutingStatementHandler) ivk
					.getTarget();
			BaseStatementHandler delegate = (BaseStatementHandler) ReflectHelper
					.getValueByFieldName(statementHandler, "delegate");

上面这个代码,表示我们首先获得RoutingStatementHandler,这个Handler也是继承了StatementHandler接口,但是基本不做具体的事情,只是再把请求转发给其他的StatementHandler。默认的BaseStatementHandler(具体执行查询的handler)怎样获得? 用delegate!就是说RoutingStatementHandler的delegate成员。

         得到了BaseStatementHandler,你就可以在这上面做些事情了。获取boundsql,然后修改boundsql:

	Object parameterObject = boundSql.getParameterObject();
获取boundsql的参数,执行某些检查,看看里面有没有包含分页参数?

        没有,则return ivk.proceed(); 继续执行链;

有,则需要根据分页信息,修改boundsql中的sql,然后return ivk.proceed();


这里修改sql有点技巧,因为不同的rdbms分页的语法都有些不同,所以我们实现诸如下面的代码:

	private String generatePagesSql(String sql, PageView page) {
		if (page != null && dialectObject != null) {
			//pageNow默认是从1,而已数据库是从0开始计算的.所以(page.getPageNow()-1)
			int pageNow = page.getPageNow();
			return dialectObject.getLimitString(sql, (pageNow<=0?0:pageNow-1)
					* page.getPageSize(), page.getPageSize());
		}
		return sql;
	}

让具体重新拼装sql的工作交给dialectObject.getLimitString(sql, (pageNow<=0?0:pageNow-1) * page.getPageSize(), page.getPageSize());去做。

        然后我们根据不同的rdbms实现不同的dialectObject.getLimitString就可以了。


        好,现在总结一下。

        你想实现分页,获取StatementHandler-> BOUNDSQL-->加工boundsql-->return ivk.proceed();

        

        下面提出一个问题: 如果我们已经实现了处理链,对请求进行拦截,并根据请求的参数进行处理,那么我们需要发什么样的请求?

        就是说我们的Mapper文件应该怎样写?我们的Mapper接口应该怎样写?我们调用的时候应该传什么参数?

先看Mapper文件:

    <select id="query" resultMap="BaseResultMap" parameterType="java.util.HashMap" >
    select 
    *
    from bai_user
    		<where>
			<if test="t.USERNAME != null and t.USERNAME != ''">
				username like '%${t.USERNAME}%'
				</if>
		</where>
  </select>

parameterType应该是一个Map类型,这样我们可以定义一个pageview,然后放在里面,到了boundsql中在根据名字取出来。

再看Mapper接口:

Mapper文件中我们传递的是Map,但我们Map中的参数类型不确定,有的是数值,有的是字符串,有的是pageview对象。所以变成如下格式:

List<baiuser> query(HashMap<Object, Object> map);

再看怎样调用。写一个测试类:

package example10.test;


import java.util.HashMap;
import java.util.Map;
import java.util.List;

import org.junit.Test;
import org.junit.Before;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.alibaba.fastjson.JSON;

import example10.dao.baiuserMapper;
import example10.model.baiuser;
import example10.util.PageView;

public class baiuserTest {
	private baiuserMapper userDao;
    @Before
	public void before(){
		@SuppressWarnings("resource")
		ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"classpath:example10/conf/spring.xml"
				});
		userDao = (baiuserMapper) context.getBean("baiuserMapper");		
	}
    
	@Test
	public void test(){
		
		HashMap<Object, Object> map = new HashMap<Object, Object>();
		baiuser user1 = new baiuser();
		user1.setUSERNAME("bai");
		
		PageView pageView = new PageView();
		
		
		map.put("paging", pageView);
		map.put("t", user1);
		
		//return getSqlSession().selectList(baiuserMapper.query ,map);
		
		List<baiuser> user = userDao.query(map);
		System.out.println(JSON.toJSONString(user));
		
		
	}
}



       示例代码:

http://download.csdn.net/detail/u013269938/7302953



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值