MyBatis插件分页

MyBatis分页有3种方法:
1.直接在映射文件里写sql语句,然后传参数
2.在接口方法里加入参数 RowBounds
3.利用插件实现分页


说说各自的优缺点:
1.太麻烦了,每个要实现分页的都要写,扩展性不强  (放弃)
2.当数据库数据多的时候,效率极低,可能会出现内存溢出
3.需要自己实现interceptor接口,但是扩展性强


这里说一说分页的思路,以mysql为例子,就是用limit来实现分页
我们为了实现分页,有一种思路就是拦截StatementHandler,在其编译sql语句前把sql改成我们要的样子,然后注入参数,最后查询得到分页效果,下面上代码


package Model;

public class Page {
	private Integer currentPage;//当前页码
	private Integer pageSize;//每页总数
	private Integer pageCount;//全部记录
	public Integer getCurrentPage() {
		return currentPage;
	}
	public void setCurrentPage(Integer currentPage) {
		this.currentPage = currentPage;
	}
	public Integer getPageSize() {
		return pageSize;
	}
	public void setPageSize(Integer pageSize) {
		this.pageSize = pageSize;
	}
	public Integer getPageCount() {
		return pageCount;
	}
	public void setPageCount(Integer pageCount) {
		this.pageCount = pageCount;
	}
	@Override
	public String toString() {
		return "Page [currentPage=" + currentPage + ", pageSize=" + pageSize + ", pageCount=" + pageCount + "]";
	}
	
}


package Mapper;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
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 org.apache.log4j.Logger;

import Model.Page;

@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class pageInterceptor implements Interceptor {

	private Page page = null;

	private Logger logger = Logger.getLogger(pageInterceptor.class);

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		// 获得源对象
		StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
		// 从源对象获得属性操作类
		MetaObject m1 = SystemMetaObject.forObject(statementHandler);
		// 多次循环分离出原始目标类
		Object object = null;
		while (m1.hasGetter("h")) {
			object = m1.getValue("h");
			m1 = SystemMetaObject.forObject(m1);
		}
		if (object == null)
			object = statementHandler;// 如果为空证明压根就没有代理对象,即没有插件用它,
		// 获取原始目标类的属性操作类
		MetaObject m2 = SystemMetaObject.forObject(object);
		while (m2.hasGetter("target")) {
			object = m2.getValue("target");
			m2 = SystemMetaObject.forObject(object);
		}
		// 计算总数sql
		culCount((Connection) invocation.getArgs()[0], m2);
		// 取出sql
		String sql = (String) m2.getValue("delegate.boundSql.sql");// 取出属性,OGNL写法
		sql = sql.trim();
		String start = sql.substring(0, 5);
		if (!start.equalsIgnoreCase(start))
			return invocation.proceed();// 如果没有select 直接跳过
		// 取出传进来的参数
		BoundSql bsql = (BoundSql) m2.getValue("delegate.boundSql");
		Page p = (Page) bsql.getParameterObject();
		if (p.getCurrentPage() == null || p.getPageSize() == null)
			// 重新拼接sql
			sql = sql + " limit " + (page.getCurrentPage() - 1) * page.getPageSize() + "," + page.getPageSize();
		else
			sql = sql + " limit " + (p.getCurrentPage() - 1) * p.getPageSize() + "," + p.getPageSize();
		p.setPageCount(page.getPageCount());
		// 放置在boundsql里
		m2.setValue("delegate.boundSql.sql", sql);
		PreparedStatement preparedStatement = (PreparedStatement) invocation.proceed();
		// 根据接口可以得知最后肯定返回的是一个Statement对象
		return preparedStatement;
	}

	private void culCount(Connection connection, MetaObject m2) {
		// 如果要执行一次查询 需要Connection Statement ResultSet
		String sql = (String) m2.getValue("delegate.boundSql.sql");
		sql = "select count(*) from (" + sql + ") $_paging";
		try {
			PreparedStatement preparedStatement = connection.prepareStatement(sql);
			ResultSet resultSet = preparedStatement.executeQuery();
			int count = 0;
			if (resultSet.next()) {
				count = resultSet.getInt(1);
			}
			page.setPageCount(count);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	@Override
	public Object plugin(Object target) {
		// TODO Auto-generated method stub
		if (target instanceof StatementHandler)
			return Plugin.wrap(target, this);// 返回代理对象
		return target;
	}

	@Override
	public void setProperties(Properties properties) {
		// TODO Auto-generated method stub
		int currentPage = Integer.parseInt(properties.getProperty("currentPage"));
		int pageSize = Integer.parseInt(properties.getProperty("pageSize"));
		page = new Page();
		page.setPageSize(pageSize);
		page.setCurrentPage(currentPage);
	}

}


<plugins>
  	<plugin interceptor="Mapper.pageInterceptor">
  		<property name="currentPage" value="1"/>
  		<property name="pageSize" value="5"/>
  	</plugin>
  </plugins>




评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值