自定义分页插件

分页需要的实体类

import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class Base implements Serializable {


    /**
     *
     */
    private static final long serialVersionUID = 1520837688012998514L;

    private Integer createdBy;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createdDate;
    private Integer updatedBy;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updatedDate;
    //删除字段状态
    private String validFlag = "Y";

    private String orderSort = "desc";//升序还是降序
    private String orderField;//排序字段

    protected int pageSize = 10; // 每页默认10条数据
    protected int page = 1; // 当前页
    protected int totalRows = 0; // 总数据数
    protected boolean pagination = false; // 是否分页


    /**
     * 动态字段. 在ibatis文件中可用“dynamicFields.xxx”方式读取动态字段值
     */
    protected Map dynamicFields = new HashMap();

    public Map getDynamicFields() {
        return dynamicFields;
    }

    public void setDynamicFields(Map dynamicFields) {
        this.dynamicFields = dynamicFields;
    }

    /**
     * 设置动态字段值.
     *
     * @param fieldName 字段名称
     * @param value     字段值
     */
    public void setField(String fieldName, Object value) {
        dynamicFields.put(fieldName, value);
    }

    /**
     * 返回动态字段值.
     *
     * @param fieldName 字段名称
     * @return 对象
     */
    public Object getField(String fieldName) {
        if (dynamicFields == null) {
            return null;
        }
        return getDynamicFields().get(fieldName);
    }

    public String getOrderSort() {
        return orderSort;
    }

    public void setOrderSort(String orderSort) {
        this.orderSort = orderSort;
    }

    public String getOrderField() {
        return orderField;
    }

    public void setOrderField(String orderField) {
        this.orderField = orderField;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public int getTotalRows() {
        return totalRows;
    }

    public void setTotalRows(int totalRows) {
        this.totalRows = totalRows;
    }

    public boolean isPagination() {
        return pagination;
    }

    public void setPagination(boolean pagination) {
        this.pagination = pagination;
    }

    public String getValidFlag() {
        return validFlag;
    }

    public void setValidFlag(String validFlag) {
        this.validFlag = validFlag;
    }

    public Integer getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(Integer createdBy) {
        this.createdBy = createdBy;
    }

    public Date getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(Date createdDate) {
        this.createdDate = createdDate;
    }

    public Integer getUpdatedBy() {
        return updatedBy;
    }

    public void setUpdatedBy(Integer updatedBy) {
        this.updatedBy = updatedBy;
    }

    public Date getUpdatedDate() {
        return updatedDate;
    }

    public void setUpdatedDate(Date updatedDate) {
        this.updatedDate = updatedDate;
    }
}

import java.io.Serializable;

public class Page implements Serializable{
    private static final long serialVersionUID = 1L;
    // 每页默认10条数据
    protected int pageSize = 10;
    // 当前页
    protected int currentPage = 1;
    // 总数据数
    protected int totalRows = 0;
    //总页数
    protected int totalPage;
    // 是否分页
    protected boolean pagination = true;

    public Page() {

    }

    public Page(Page clonePage) {
        this.pageSize = clonePage.pageSize;
        this.currentPage = clonePage.currentPage;
        this.totalRows = clonePage.totalRows;
        this.totalPage = clonePage.totalPage;
        this.pagination = clonePage.pagination;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public int getCurrentPage() {
        return currentPage;
    }

    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }

    public int getTotalRows() {
        return totalRows;
    }

    public void setTotalRows(int totalRows) {
        this.totalRows = totalRows;
        if (pageSize == 0) {
            pageSize = 10;
        }
        totalPage = (totalRows / pageSize) + (totalRows % pageSize > 0 ? 1 : 0);
    }

    public boolean isPagination() {
        return pagination;
    }

    public void setPagination(boolean pagination) {
        this.pagination = pagination;
    }

    public int getTotalPage() {
        return totalPage;
    }

    public void setTotalPage(int totalPage) {
        this.totalPage = totalPage;
    }
}

public class PageContext {

    private static ThreadLocal<Page> context = new ThreadLocal<Page>();

    public static Page getContext() {
        Page page = context.get();
        if (page == null) {
            page = new Page();
            context.set(page);
        }
        return page;
    }

    public static void remove() {
        context.remove();
    }

}

分页插件


import org.apache.ibatis.executor.statement.BaseStatementHandler;
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.plugin.*;
import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
import org.springframework.util.StringUtils;

import javax.xml.bind.PropertyException;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

//@Intercepts({ @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }) })
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class})})
public class PageInterceptor implements Interceptor {
    private Dialect dialect = null;

    /**
     * 拦截后要执行的方法
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        if (invocation.getTarget() instanceof RoutingStatementHandler) {
            RoutingStatementHandler routingStatementHandler = (RoutingStatementHandler) invocation.getTarget();
            Object obj = routingStatementHandler.getParameterHandler().getParameterObject();
            Page page = PageContext.getContext();
            if (obj instanceof Base) {
                Base base = (Base) obj;
                page.setPageSize(base.getPageSize());
                page.setCurrentPage(base.getPage());
                page.setPagination(base.isPagination());
                if (page == null || !page.isPagination()) {
                    // 不需要分页,则直接执行
                    return invocation.proceed();
                }
            } else {
                // 不需要分页,则直接执行
                return invocation.proceed();
            }


            RoutingStatementHandler statementHandler = (RoutingStatementHandler) invocation.getTarget();
            BaseStatementHandler delegate = (BaseStatementHandler) ReflectUtil.getValueByFieldName(statementHandler, "delegate");
            BoundSql boundSql = delegate.getBoundSql();

            // 获取原始sql
            String originalSql = boundSql.getSql();

            // 求总行数
            Connection connection = (Connection) invocation.getArgs()[0];
            if (page.getTotalRows() == 0 || page.getCurrentPage() == 1) {
                int totalRows = getTotalRows(connection, delegate, page);
                // 设置总行数
                page.setTotalRows(totalRows);
            }
            // 目标sql执行分页后,设置pagination==false,(避免关联sql执行分页)
            page.setPagination(false);
            // 构造用于分页查询的sql
            reboundSql(boundSql, page, originalSql);
        }

        return invocation.proceed();
    }

    /**
     * 重构分页查询语句
     *
     * @param page
     * @param originalSql
     * @throws SecurityException
     * @throws NoSuchFieldException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     */
    private void reboundSql(BoundSql boundSql, Page page, String originalSql) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
        String pageSql = generatePagesSql(originalSql, page);
        // 将分页sql语句反射回BoundSql.
        ReflectUtil.setValueByFieldName(boundSql, "sql", pageSql);
    }

    /**
     * 根据数据库方言,生成特定的分页sql
     *
     * @param sql
     * @param page
     * @return
     */
    private String generatePagesSql(String sql, Page page) {
        if (dialect == null) {
            return sql;
        }
        return dialect.getLimitString(sql, (page.getCurrentPage() - 1) * page.getPageSize(), page.getPageSize());
    }

    /**
     * 求总行数
     *
     * @return
     * @throws SQLException
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     * @throws NoSuchFieldException
     * @throws SecurityException
     */
    private int getTotalRows(Connection connection, BaseStatementHandler delegate, Page page) throws SQLException, SecurityException, NoSuchFieldException,
            IllegalArgumentException, IllegalAccessException {

        MappedStatement mappedStatement = (MappedStatement) ReflectUtil.getValueByFieldName(delegate, "mappedStatement");

        BoundSql boundSql = delegate.getBoundSql();
        Object parameterObject = boundSql.getParameterObject();
        String originalSql = boundSql.getSql();
        String countSql = "select count(0) from (" + originalSql + ") t"; // 记录统计
        PreparedStatement countStatement = connection.prepareStatement(countSql);
        ReflectUtil.setValueByFieldName(boundSql, "sql", countSql);

        DefaultParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);
        parameterHandler.setParameters(countStatement);
        ResultSet rs = countStatement.executeQuery();
        int count = 0;
        if (rs.next()) {
            count = rs.getInt(1);
        }
        rs.close();
        countStatement.close();

        return count;

    }

    /**
     * 拦截器对应的封装原始对象的方法
     */
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    /**
     * 设置注册拦截器时设定的属性
     */
    @Override
    public void setProperties(Properties properties) {
        String databaseType = properties.getProperty("dialect");
        if (StringUtils.isEmpty(databaseType)) {
            try {
                throw new PropertyException("databaseType property is not found!");
            } catch (PropertyException e) {
                e.printStackTrace();
            }
        }

        if ("mysql".equalsIgnoreCase(databaseType)) {
            dialect = new MySql5Dialect();
        } else if ("oracle".equalsIgnoreCase(databaseType)) {
            dialect = new OracleDialect();
        }
    }

    /**
     * 利用反射进行操作的一个工具类
     */
    private static class ReflectUtil {
        /**
         * 设置obj对象fieldName的属性值
         *
         * @param obj
         * @param fieldName
         * @param value
         * @throws SecurityException
         * @throws NoSuchFieldException
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         */
        public static void setValueByFieldName(Object obj, String fieldName, Object value) throws SecurityException, NoSuchFieldException, IllegalArgumentException,
                IllegalAccessException {
            Field field = obj.getClass().getDeclaredField(fieldName);
            if (field.isAccessible()) {
                field.set(obj, value);
            } else {
                field.setAccessible(true);
                field.set(obj, value);
                field.setAccessible(false);
            }
        }

        /**
         * 获取obj对象fieldName的属性值
         *
         * @param obj
         * @param fieldName
         * @return
         * @throws SecurityException
         * @throws NoSuchFieldException
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         */
        public static Object getValueByFieldName(Object obj, String fieldName) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
            Field field = getFieldByFieldName(obj, fieldName);
            Object value = null;
            if (field != null) {
                if (field.isAccessible()) {
                    value = field.get(obj);
                } else {
                    field.setAccessible(true);
                    value = field.get(obj);
                    field.setAccessible(false);
                }
            }
            return value;
        }

        /**
         * 获取obj对象fieldName的Field
         *
         * @param obj
         * @param fieldName
         * @return
         */
        public static Field getFieldByFieldName(Object obj, String fieldName) {
            for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
                try {
                    return superClass.getDeclaredField(fieldName);
                } catch (NoSuchFieldException e) {
                }
            }
            return null;
        }
    }
}

返回的对象



import com.fasterxml.jackson.annotation.JsonInclude;

import java.io.Serializable;
import java.util.HashMap;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Response implements Serializable{

	private int status = “SUCCESS”;

	public int getStatus() {
		return status;
	}

	public void setStatus(int status) {
		this.status = status;
	}

	public static Success success() {
		return new Success(new HashMap<>());
	}

	public static Success success(Object data) {
		Page page = PageContext.getContext();
		Page newPage = new Page(page);
		PageContext.remove();
		if (newPage.getTotalRows() > 0) {
			// 有分页数据,只能用getTotalRows判断
			// page.isPagination()在执行分页后设置为false,避免关联sql执行分页
			return new Success(data, newPage,newPage.totalRows);
		}
		return new Success(data);
	}
	
	public static Success success(int code, String msg) {
		return new Success(code, msg);
	}
	
	public static Failure fail() {
		return fail(IccConstants.FAIL, "亲~系统繁忙,请稍后再试!");
	}

	public static Failure fail(String msg) {
		return fail(1, msg);
	}
	public static FailureHint failHint(String msg) {
		return failHint(1, msg);
	}

	public static Failure fail(int code, String msg) {
		return new Failure(code, msg);
	}
	public static FailureHint failHint(int code, String msg) {
		return new FailureHint(code, msg);
	}

}

如下返回就会自动分页和填充数据

 @Override
    public Response serviceOrderList(ServiceOrder serviceOrder) {
        List<ServiceOrder> list = orderMapper.serviceOrderList(serviceOrder);
        return Response.success(list);
    }

mybatis-config.xml 加上如下代码

<!-- 分页插件  下面**.**写分页插件包名 -->
    <plugins>
        <plugin interceptor="**.**.PageInterceptor">
            <property name="dialect" value="mysql"/>
        </plugin>
    </plugins>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值