Mybatis学习- 拦截器-实现分页
来源:互联网 发布:淘宝商城女装朵以 编辑:程序博客网 时间:2024/05/21 08:58
本文的程序基本上都不是我自己实现的,网上有好多现成的例子。我只是根据自己理解,对整个过程进行了说明。
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; @Beforepublic void before(){@SuppressWarnings("resource")ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"classpath:example10/conf/spring.xml"});userDao = (baiuserMapper) context.getBean("baiuserMapper");} @Testpublic 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
- Mybatis学习- 拦截器-实现分页
- MyBatis拦截器实现分页
- Mybatis拦截器实现分页
- Mybatis拦截器实现分页
- mybatis拦截器分页学习
- Mybatis通过拦截器实现分页查询
- 通过Mybatis拦截器实现分页
- MyBatis 拦截器 (实现分页功能)
- MyBatis实现拦截器分页功能
- MyBatis拦截器实现分页功能
- mybatis分页拦截器的实现
- Mybatis拦截器实现分页和存储过程实现分页
- mybatis分页拦截器
- Mybatis - 分页拦截器
- Mybatis拦截器分页
- mybatis分页拦截器
- MyBatis拦截器分页
- Mybatis分页拦截器
- 小屏,你好!—移动端网站赏析
- 【原创】Ubuntu监测动态环境(发送视频到邮箱、NAT模式下端口映射)
- 高手建站优化几步环节
- 关键词排名的查询方法
- springSecurity源码分析——DelegatingFilterProxy类的作用
- Mybatis学习- 拦截器-实现分页
- xmpp Use of undeclared identifier 'ddLogLevel'
- Visa将为基于云的安全移动支付提供支持
- iOS 自定义UITabbar边框问题
- Inflater与findViewById()区别
- 《Oracle 网络配置 本人最感兴趣的章节之一》
- JAVA大数阶乘
- Cocos2d-x 3.0 中文基础教程-精灵帧缓存(SpriteFrameCache)
- 124暖暖简欧风