【Mybatis】Mybatis 分页-拦截器方式

##实现环境 Spring + Mybatis + MySQL ##实现原理 分页拦截器,主要是对参数中含有Page对象的函数进行分页处理,主要利用拦截器拦截到当前带有Page对象作为参数的方法,获取到Connection,StateMent,以及执行的SQL,进一步进行操作,实现获取总页数,结果的一种方式 ##实现代码

  • 工具类

    使用反射机制,获取对象中的属性,和设置属性值

    代码如下:ReflectUtil.java

    import java.lang.reflect.Field; /**

    • Desc : TODO Author: 山野痞夫 Date : 2015年8月25日 Time: : 上午9:56:23 / public class ReflectUtil { /*

      • 利用反射获取指定对象的指定属性
      • @param obj 目标对象
      • @param fieldName 目标属性
      • @return 目标属性的值 */ public static Object getFieldValue(Object obj, String fieldName) { Object result = null; final Field field = ReflectUtil.getField(obj, fieldName); if (field != null) { field.setAccessible(true); try { result = field.get(obj); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } return result; }

      /**

      • 利用反射获取指定对象里面的指定属性
      • @param obj目标对象
      • @param fieldName 目标属性
      • @return 目标字段 */ private static Field getField(Object obj, String fieldName) { Field field = null; for (Class<?> clazz = obj.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) { try { field = clazz.getDeclaredField(fieldName); break; } catch (NoSuchFieldException e) { e.printStackTrace(); } } return field; }

      /**

      • 利用反射设置指定对象的指定属性为指定的值
      • @param obj 目标对象
      • @param fieldName目标属性
      • @param fieldValue 目标值 */ public static void setFieldValue(Object obj, String fieldName, String fieldValue) { final Field field = ReflectUtil.getField(obj, fieldName); if (field != null) { try { field.setAccessible(true); field.set(obj, fieldValue); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } }
  • 拦截器的实现类

    实现拦截器接口

    代码如下:SpringMybatisPageInterceptor.java

    import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import java.util.Map; import java.util.Properties; import org.apache.ibatis.executor.statement.RoutingStatementHandler; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.ParameterMapping; 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 com.icaopan.util.ReflectUtil; /**

    • Desc : Mybatis分页拦截器 Author: 山野痞夫 Date : 2015年8月25日 Time: : 下午4:14:14 */ @Intercepts({ @Signature(method = "prepare", type = StatementHandler.class, args = { Connection.class }) }) public class SpringMybatisPageInterceptor implements Interceptor {

      /** 拦截器 */ public Object intercept(Invocation invocation) throws Throwable { //拦截执行的Handler final RoutingStatementHandler handler = (RoutingStatementHandler) invocation.getTarget(); //获取分页拦截器必要的参数 final StatementHandler delegate = (StatementHandler) ReflectUtil.getFieldValue(handler, "delegate"); //获取执行的SQL final BoundSql boundSql = delegate.getBoundSql(); //获取执行的参数 final Object obj = boundSql.getParameterObject(); //获取StateMent final MappedStatement mappedStatement=(MappedStatement)ReflectUtil.getFieldValue(delegate, "mappedStatement"); //判断参数是否有Page参数,如果有则按照 if (obj instanceof Page) { Page resultPage = new Page(); final Page page = (Page) obj; final String sql = boundSql.getSql(); //计算总的条目数 final String countSQL = getMysqlCountSql(new StringBuffer(sql)); int totalCount = getCounts(mappedStatement, countSQL ,boundSql,page); //获取分页后的结果 final String pageSql = this.getMysqlPageSql(page, new StringBuffer(sql)); ReflectUtil.setFieldValue(boundSql, "sql", pageSql); page.setTotal(totalCount); } return invocation.proceed();

      }

      /** 定义使用的拦截器 */ public Object plugin(Object obj) { return Plugin.wrap(obj, this); }

      /** 获取属性信息 */ public void setProperties(Properties properties) {

      }

      /**

      • 组装分页SQL
      • @param page 分页javaBean
      • @param sqlBuffer 组装好的分页SQL
      • @return */ private String getMysqlPageSql(Page page, StringBuffer sqlBuffer) { sqlBuffer.append(" limit ").append(page.getLimitStart()).append(",").append(page.getLimitend()); return sqlBuffer.toString(); }

      /**

      • 组装查询数量的SQL
      • @param sqlBuffer 组装好的分页SQL
      • @return / private String getMysqlCountSql(StringBuffer sqlBuffer) { StringBuffer buffer = new StringBuffer(); buffer.append("select count() from ("); buffer.append(sqlBuffer); buffer.append(") as total"); return buffer.toString(); }

      /**

      • 获取总页数
      • @param mappedStatement
      • @param countSQL
      • @return */ private int getCounts(MappedStatement mappedStatement, String countSQL ,BoundSql boundSql , Page page) { final ParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, page, boundSql); Connection connection = null; ResultSet rs = null; PreparedStatement countStmt = null; int totpage = 0; try { //获取连接 connection = mappedStatement.getConfiguration().getEnvironment().getDataSource().getConnection(); //预处理SQL countStmt = connection.prepareStatement(countSQL); //给预处理SQL 赋值 parameterHandler.setParameters(countStmt); //查询预处理的SQL rs = countStmt.executeQuery(); if (rs.next()) { totpage = rs.getInt(1); } } catch (SQLException e) { e.printStackTrace(); } finally { //关闭释放资源 try { if(rs!=null)rs.close(); if(countStmt!=null)countStmt.close(); if(connection!=null)connection.close(); } catch (SQLException e) { e.printStackTrace(); } } return totpage; } }
  • Spring文件配置

    <!-- 此处替换成自己的包地址 -->

    <bean id="statementHandlerInterceptor" class="com.*.page.SpringMybatisPageInterceptor" /> <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 , web数据库 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 自动扫描mapping.xml文件 --> <property name="mapperLocations" value="classpath:web/*/*.xml"></property> <!-- 加载分页插件 --> <property name="plugins"> <array> <ref local="statementHandlerInterceptor" /> </array> </property> </bean>

  • Page代码

      import java.util.List;
      import java.util.Map;
    
      /**
       * @Title: page.java 
       * @Package com.icaopan.page 
       * @Description: TODO(分页参数) 
       * @author 山野痞夫 
       * @date 2015年6月13日 下午2:24:52 
       * @version V1.0   
       */
      public class Page {
    
      	private int current  = 1; //当前页
      	private int rowCount = 10;//页数
      	@SuppressWarnings("rawtypes")
      	private List rows;		  //查询出来的数据
       	private Map<String,Object> params; //参数
      	private int  limitend;			//计算后的结束页
    
      	public int getCurrent() {
      		return current;
      	}
      	public void setCurrent(int current) {
      		this.current = current;
      	}
      	public int getRowCount() {
      		return rowCount;
      	}
      	public void setRowCount(int rowCount) {
      		this.rowCount = rowCount;
      	}
      	public List getRows() {
      		return rows;
      	}
      	public void setRows(List rows) {
      		this.rows = rows;
      	}
      	public int getTotal() {
      		return total;
      	}
      	public void setTotal(int total) {
      		this.total = total;
      	}
      	public int getLimitStart() {
      		return (current-1)*rowCount;
      	}
      	public void setLimitStart(int limitStart) {
      		this.limitStart = limitStart;
      	}
      	public int getLimitend() {
      		return rowCount;
      	}
      	public void setLimitend(int limitend) {
      		this.limitend = limitend;
      	}
      	public Map<String, Object> getParams() {
      		return params;
      	}
      	public void setParams(Map<String, Object> params) {
      		this.params = params;
      	}
      }
    

##后记 1.在拦截器实现中有的地方比较挫,希望大家进行指正。 2.个人邮箱:ifaxin@yeah.net ##附件 源代码

转载于:https://my.oschina.net/ifaxin/blog/496945

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值