刚开始项目,需要用到mybatis分页,网上看了很多插件,其实实现原理基本都大同小异,但是大部分都只给了代码,注释不全,所以参考了很多篇文章(每篇文章偷一点代码,评出来自己的,半抄袭),才自己模仿着写出了一个适合自己项目的分页插件,话不多说,直接上代码,相比大部分文章,注释算很完整了
最重要的拦截器
package com.dnkx.interceptor; import java.sql.*; import java.util.HashMap; import java.util.Properties; import org.apache.ibatis.executor.resultset.ResultSetHandler; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.plugin.Intercepts; import org.apache.ibatis.plugin.Invocation; import org.apache.ibatis.plugin.Plugin; import org.apache.ibatis.plugin.Signature; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.SystemMetaObject; import com.dnkx.pojo.Page; /** * * 分页拦截器,用于拦截需要进行分页查询的操作,然后对其进行分页处理。 * 利用拦截器实现Mybatis分页的原理: * 要利用JDBC对数据库进行操作就必须要有一个对应的Statement对象,Mybatis在执行Sql语句前就会产生一个包含Sql语句的Statement对象,而且对应的Sql语句 * 是在Statement之前产生的,所以我们就可以在它生成Statement之前对用来生成Statement的Sql语句下手。在Mybatis中Statement语句是通过RoutingStatementHandler对象的 * prepare方法生成的。所以利用拦截器实现Mybatis分页的一个思路就是拦截StatementHandler接口的prepare方法,然后在拦截器方法中把Sql语句改成对应的分页查询Sql语句,之后再调用 * StatementHandler对象的prepare方法,即调用invocation.proceed()。 * 对于分页而言,在拦截器里面我们还需要做的一个操作就是统计满足当前条件的记录一共有多少,这是通过获取到了原始的Sql语句后,把它改为对应的统计语句再利用Mybatis封装好的参数和设 * 置参数的功能把Sql语句中的参数进行替换,之后再执行查询记录数的Sql语句进行总记录数的统计。 * * 解释一下插件中可能要用到的几个类: * MetaObject:mybatis提供的一个基于返回获取属性值的对象的类 * BoundSql : 在这个里面可以获取都要执行的sql和执行sql要用到的参数 * MappedStatement : 这个可以得到当前执行的sql语句在xml文件中配置的id的值 * RowBounds : 是mybatis内存分页要用到的。 * ParameterHandler : 是mybatis中用来替换sql中?出现的值的. * * @author 李小拐 2016年11月9日 10:59:04 */ @Intercepts({ @Signature(type=StatementHandler.class,method="prepare",args={Connection.class}), @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class}) }) public class PageInterceptor implements Interceptor{ //拦截分页关键字 private static final String SELECT_ID="page"; //插件运行的代码,它将代替原有的方法,要重写最重要的intercept了 @Override public Object intercept(Invocation invocation) throws Throwable { if (invocation.getTarget() instanceof StatementHandler) { //这里我们有一个设定 如果查询方法含有Page 就进行分页 其他方法无视 //所以就要获取方法名 StatementHandler statementHandler=(StatementHandler)invocation.getTarget(); MetaObject metaObject=SystemMetaObject.forObject(statementHandler); MappedStatement mappedStatement=(MappedStatement)metaObject.getValue("delegate.mappedStatement"); String selectId=mappedStatement.getId(); String methorName=selectId.substring(selectId.lastIndexOf(".")+1).toLowerCase(); //然后判断下 如果含有Page 就获取sql if(methorName.contains(SELECT_ID)){ BoundSql boundSql=(BoundSql)metaObject.getValue("delegate.boundSql"); //分页参数作为参数对象parameterObject的一个属性 String sql=boundSql.getSql(); System.out.println("获取到的sql:"+sql); HashMap<String, Object> map=(HashMap<String, Object>)(boundSql.getParameterObject()); //Page page=(Page)(boundSql.getParameterObject()); Page page=(Page)map.get("page"); // 重写sql String countSql=concatCountSql(sql); String pageSql=concatPageSql(sql,page); // System.out.println("重写的 count sql :"+countSql); System.out.println("重写的 select sql :"+pageSql); Connection connection = (Connection) invocation.getArgs()[0]; PreparedStatement countStmt = null; ResultSet rs = null; int totalCount = 0; try { countStmt = connection.prepareStatement(countSql); rs = countStmt.executeQuery(); if (rs.next()) { totalCount = rs.getInt(1); } } catch (SQLException e) { System.out.println("Ignore this exception"+e); } finally { try { rs.close(); countStmt.close(); } catch (SQLException e) { System.out.println("Ignore this exception"+ e); } } metaObject.setValue("delegate.boundSql.sql", pageSql); //绑定count page.setNumCount(totalCount); } } return invocation.proceed(); } // 拦截类型StatementHandler,重写plugin方法 @Override public Object plugin(Object target) { if (target instanceof StatementHandler) { return Plugin.wrap(target, this); }else { return target; } } @Override public void setProperties(Properties properties) { } //改造sql public String concatCountSql(String sql){ //StringBuffer sb=new StringBuffer("select count(*) from "); /*sql=sql.toLowerCase(); if(sql.lastIndexOf("order")>sql.lastIndexOf(")")){ sb.append(sql.substring(sql.indexOf("from")+4, sql.lastIndexOf("order"))); }else{ sb.append(sql.substring(sql.indexOf("from")+4)); }*/ StringBuffer sb=new StringBuffer(); sql=sql.toLowerCase(); if(sql.lastIndexOf("order")>0){ sql=sql.substring(0,sql.indexOf("order")); } sb.append("select count(*) from ("+sql+") tmp"); return sb.toString(); } public String concatPageSql(String sql,Page page){ StringBuffer sb=new StringBuffer(); sb.append(sql); sb.append(" limit ").append(page.getPageBegin()).append(" , ").append(page.getPageSize()); return sb.toString(); } } 分页对象Page类 [java] view plain copy package com.dnkx.pojo; import java.util.HashMap; import java.util.Map; /** * * 分页查询辅助类 * @author 李小拐 2016年11月9日 13:55:37 */ public class Page { //----------分页----------- private int pageSize;//每页显示条数 private int pageCurrentPage;//第几页 private int pageBegin;//开始位置 private int numCount;//总条数 private int pageTotal;//总条数 private String orderField = "";//控制排序页面显示的 private String orderDirection = ""; public Page(){ } public Page(int pageSize, int pageCurrentPage) { super(); this.pageSize = pageSize; this.pageCurrentPage = pageCurrentPage; } public Page(Map<String, String> map){ if(map.get("pageNum")!=null){ this.setPageCurrentPage(this.pageCurrentPage = Integer.parseInt(map.get("pageNum")));//要查询的页数 }else{ this.setPageCurrentPage(1);//设置初始值 } if(map.get("numPerPage")!=null){ this.setPageSize(Integer.parseInt(map.get("numPerPage")));//每页显示条数 }else{ this.setPageSize(5);//设置初始值 } if(map.get("orderField")!=null){ this.setOrderField(map.get("orderField")); } if(map.get("orderDirection")!=null){ this.setOrderDirection(map.get("orderDirection")); } } public int getPageCurrentPage() { return pageCurrentPage; } public void setPageCurrentPage(int pageCurrentPage) { this.pageCurrentPage = pageCurrentPage; } public int getNumCount() { return numCount; } public void setNumCount(int numCount) { this.numCount = numCount; } public int getPageTotal() { return (numCount%pageSize>0)?(numCount/pageSize+1):(numCount/pageSize); } public void setPageTotal(int pageTotal) { this.pageTotal = pageTotal; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getPageBegin() { return pageSize*(pageCurrentPage-1); } public void setPageBegin(int pageBegin) { this.pageBegin = pageBegin; } public String getOrderField() { return orderField; } public void setOrderField(String orderField) { this.orderField = orderField; } public String getOrderDirection() { return orderDirection; } public void setOrderDirection(String orderDirection) { this.orderDirection = orderDirection; } public static Page getPage(int pageSize, int pageCurrentPage){ return new Page(pageSize,pageCurrentPage); } public static Page getPage(Map map){ return new Page(map); } }
Controller里面调用方式
public String list(HttpServletRequest request) { long a=System.currentTimeMillis(); HashMap<String,Object> map=GetRequestMap.getMap(request);//自己封装的方法,取request的参数 Page page= Page.getPage(map);//初始化page map.put("page", page);//把page对象放入参数集合(这个map是mybatis要用到的,包含查询条件,排序,分页等) //控制排序页面显示的 map.put(map.get("orderField")+"", map.get("orderDirection")); List<Employee> list=employeeService.getListPage(map); request.setAttribute("emlist", list); request.setAttribute("page", page); request.setAttribute("map", map); //取page相关属性 page.getNumCount();//总条数 page.getPageTotal();//总页数 long b=System.currentTimeMillis(); System.out.println("---------耗时:"+(b-a)+"ms"); return "basic/employee_list"; }
最后,spring里面配置插件
<bean id="PageInterector" class="com.dnkx.interceptor.PageInterceptor"></bean> <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 自动扫描mapping.xml文件 --> <property name="mapperLocations" value="classpath:com/dnkx/mapping/*.xml"></property> <property name="plugins"> <ref bean="PageInterector"/> </property> </bean>
好了,到此结束,本文仅供参考!也期待大神提意见
本文向大家介绍自己动手写的jquery分页控件(非常简单实用),包括了自己动手写的jquery分页控件(非常简单实用)的使用技巧和注意事项,需要的朋友参考一下 最近接了一个项目,其中有需求要用到jquery分页控件,上网也找到了需要分页控件,各种写法各种用法,都是很复杂,最终决定自己动手写一个jquery分页控件,全当是练练手了。写的不好,还请见谅,本分页控件在chrome测试过,其他的兼容性不知
本文向大家介绍分享一个自己动手写的jQuery分页插件,包括了分享一个自己动手写的jQuery分页插件的使用技巧和注意事项,需要的朋友参考一下 工作需要一个JS分页插件,心想自己动手写一个吧,一来上网找一个不清楚代码结构的,出了问题难以解决,而且网上的插件所包含的功能太多,有些根本用不到,就没必要加载那段JS,二来想起没写过jQuery插件,就当练一下手了,好了,先看结果: http://demo
本文向大家介绍自己动手手写jQuery插件总结,包括了自己动手手写jQuery插件总结的使用技巧和注意事项,需要的朋友参考一下 jQuery是继Prototype之后的又一款优秀的JavaScript框架,深受广大开发者热爱,用户甚广。而jQuery一个很好的地方在 于用户的自定义,即我们可以书写自己的插件来完善jQuery的各项功能,定制自己所需要的功能,剔除冗余的代码,在页面加载时候可以有一定
本文向大家介绍Java简单实现SpringMVC+MyBatis分页插件,包括了Java简单实现SpringMVC+MyBatis分页插件的使用技巧和注意事项,需要的朋友参考一下 1.封装分页Page类 2.封装分页插件 3.MyBatis配置文件:mybatis-config.xml 4.分页拦截器 5.Spring配置 6.SpringMVC配置拦截器
React-Native的核心思想就是组件化,相当于MVC的view,因此开发应用的最佳方式就是将功能组件化。 一、最简单的方式 这里我们实现一个最简单的组件,就是邮件的末尾署名的组件。组件意味着复用,意味着统一。现在有这样一个需求,我们需要根据不同用户发送邮件时,生成每个用户的名片(即邮件末尾的署名)。 1、一般一开始的实现方式如下,直接将组件内容写到功能需求的地方: <View> <V
本文向大家介绍自己动手写一个java版简单云相册,包括了自己动手写一个java版简单云相册的使用技巧和注意事项,需要的朋友参考一下 动手写一个java版简单云相册,实现的功能是: 用户可以一次上传一个至多个文件。 用户可以下载其他人上传的图片。 用户可以查看其他所有人的图片。 用户只能删除通过自己IP上传的图片。 用到的技术: 文件上传下载、设计模式、Dom4j、xPath等。 先看下2个页面: