您的位置:首页 > 其它

手写Mybatis分页插件

2018-03-08 23:13 411 查看
    之前涉及到mybatis分页时,都是先查询一遍总和,再用Limit,导致了项目中有大量的冗余代码,非常的难看,网上不管是框架,还是人家提到的各种自以为是的解决办法,基本上都是下面两种:
    1.先查一下总条数,再用Limt
     2.直接查出所有,再用subList截取
   就我个人而言,我觉的两种做法都很愚蠢,但是呢我还是没找到一种很好的解决方案,也就只能用框架来解决这种事情,使代码更简洁,总之,相同的事情都可以抽取出来,封装成框架,像我今天所说的这个就是传入分页参数,然后自动帮我们补齐 select count(0) from "sql"和 "sql"+"limit ?,?",很简单,mybatis为我们提供了拦截器插件,可以方便我们来操作.

   Mybatis的配置文件加上这一句

 <plugins>
<plugin interceptor="MyInterceptor"></plugin>
</plugins>
   核心拦截类
  package com.yayiabc.common.utils;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;

import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.ExecutorException;
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.mapping.ParameterMode;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.reflection.property.PropertyTokenizer;
import org.apache.ibatis.scripting.xmltags.ForEachSqlNode;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.mysql.jdbc.Connection;

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

private final Logger logger=LoggerFactory.getLogger(MyInterceptor.class);

/**
* 插件运行的代码,它将代替原有的方法,要重写最重要的intercept方法
*/
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();
if(selectId.matches(".*Page$")){
BoundSql boundSql=(BoundSql)metaObject.getValue("delegate.BoundSql");
String sql=boundSql.getSql();
HashMap<String,Object> hashMap=(HashMap<String, Object>)(boundSql.getParameterObject());
MyPage myPage=(MyPage)hashMap.get("page");
//重写SQL
String countSql="select count(0) from "+sql;
String pageSql=sql+"limit "+myPage.getPageBegin()+","+myPage.getPageSize();

Connection connection=(Connection)invocation.getArgs()[0];

PreparedStatement cStatement=null;
ResultSet rs=null;
int totalCount=0;
try {
cStatement=connection.prepareStatement(countSql);
setParameters(cStatement,mappedStatement,boundSql,boundSql.getParameterObject());
rs=cStatement.executeQuery();
if(rs.next()){
totalCount=rs.getInt(1);
}
} catch (Exception e) {
logger.info(e.getMessage());
}finally {
try {
rs.cl
b314
ose();
cStatement.close();
} catch (Exception e) {
logger.error("SQLException", e);
}
}
metaObject.setValue("delegate.boundSql.sql", pageSql);

myPage.setNumCount(totalCount);
}

}

return invocation.proceed();
}

private void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql,
Object parameterObject) throws SQLException {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
Configuration configuration = mappedStatement.getConfiguration();
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
MetaObject metaObject = parameterObject == null ? null: configuration.newMetaObject(parameterObject);
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
PropertyTokenizer prop = new PropertyTokenizer(propertyName);
if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else if (boundSql.hasAdditionalParameter(propertyName)) {
value = boundSql.getAdditionalParameter(propertyName);
} else if (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX)&& boundSql.hasAdditionalParameter(prop.getName())) {
value = boundSql.getAdditionalParameter(prop.getName());
if (value != null) {
value = configuration.newMetaObject(value).getValue(propertyName.substring(prop.getName().length()));
}
} else {
value = metaObject == null ? null : metaObject.getValue(propertyName);
}
TypeHandler typeHandler = parameterMapping.getTypeHandler();
if (typeHandler == null) {
throw new ExecutorException("There was no TypeHandler found for parameter "+ propertyName + " of statement "+ mappedStatement.getId());
}
typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType());
}
}
}

}

public Object plugin(Object arg0) {
//
return null;
}

public void setProperties(Properties arg0) {
//

}

}分页辅助类 myPagepackage com.yayiabc.common.utils;

import java.util.Map;

public class MyPage {
//----------分页-----------
private int pageSize;//每页显示条数
private int pageCurrentPage;//第几页
private int pageBegin;//开始位置
private int numCount;//总条数
private int pageTotal;//总条数

private String orderField = "";//控制排序页面显示的
private String orderDirection = "";

public MyPage(){

}

public MyPage(int pageSize, int pageCurrentPage) {
super();
this.pageSize = pageSize;
this.pageCurrentPage = pageCurrentPage;
}

public MyPage(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 MyPage getPage(int pageSize, int pageCurrentPage){
return new MyPage(pageSize,pageCurrentPage);
}

public static MyPage getPage(Map map){
return new MyPage(map);
}

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: