项目总结: MyBatis-paginator实现分页

麻阳
2023-12-01

写在正文前面的一些话

最近公司任务比较紧(为自己懒没写博客找的理由还不错), 关于博客的更新停滞了一段时间.最近一直在”仔细揣摩”公司项目的各种历史存储过程,那个苦啊,看的整个人不行不行的,关键是还得把诸如此类的存储过程改成java代码,还得自己写各种测试用例,对于我这种刚进公司的业务小白来说,实在是有点那啥了…
言归正传,幸好我们组长看我做事比较认真,最近交给我一个”光荣使命”:给公司分页插件添加一个支持字段排序的小功能(其实就是动态给业务SQL加上order by的东西),还好幸不辱命,还得以一窥 MyBatis-paginator 插件的其他使用,特意总结下,分享给寥寥无几的数人…

MyBatis-paginator 简介

MyBatis-paginator 是github上的一个开源项目, 主要作用就是从java后台获取分页数据,并结合另外一个基于jQuery的表格控件:mmgrid用于展示后台分页数据.
开源项目地址为: https://github.com/miemiedev

使用插件

mybatis-config.xml 设置分页插件

<plugins>
    <plugin interceptor="com.xxx.xxx.framework.mybatis.paginator.OffsetLimitInterceptor">
        <!-- 这是一个自定义方言类,就是定制化SQL的java类 -->
        <property name="dialectClass" value="com.xxx.xxx.framework.mybatis.paginator.dialect.SQLServer2005Dialect" />
    </plugin>
</plugins>

Controller层

@Controller
@RequestMapping(value = "/acl/role")
public class RoleController {
    /**
     * 
     * @param queryDto  查询Dto
     * @param page      当前页码
     * @param limit     每页最大记录数
     * @param sortStr   排序字段
     * @return
     */
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public @ResponseBody
    Page<Role> list(RoleQueryDto queryDto, 
            @RequestParam (value = "page", defaultValue = "1") Integer page,
            @RequestParam(value = "limit", required = false) Integer limit,
            @RequestParam(value= "sort", required = false) String sortStr){
        return roleService.findPage(queryDto, MyPage.create(page, limit, sortStr));
    }
}

public class RoleServiceImpl implements RoleService {
        public Page<Role> findPage(RoleQueryDto queryDto, MyPage page) {
        return roleDao.selectByRoleDto(queryDto, page.getRowBounds()).getPage();
    }
}

mmgrid使用分页插件

在这里说下mmgrid中使用分页插件的写法:

var cols = [
    {title:'创建时间', name:'createdDate' , align:'center',sortable: true,width:120,lockWidth:true}
            ];
mmgrid = $('#mmgrid_table').mmGrid({//表格控件渲染
            multiSelect:false,//是否可以多选
            checkCol:false,//是否显示复选框
            cols: cols,
            url: xxx('/acl/role/list'),//请求后台url
            params : function () {
                return $('.query-ul .form-control').serializeObject();
            },
            sortStatus: 'desc',//排序方向
            fullWidthRows:true,//第一次加载表格时,列充满表格自动
            remoteSort: true,
            root:"content",//渲染后台数据
            nowrap:false,
            width: 'auto',
            height: 'auto',
            method: 'get',
            remoteSort : true,//是否启用后台排序
            plugins: [
                $('#page').mmPaginator({totalCountName:"totalElements"})//前台使用分页插件
            ]
        });

        return mmgrid;

当你请求后台: acl/role/list时, 会默认给后台传
“page:xxx”,
“limit:xxx”,
“sort:createdDate.asc” // 需要排序的字段及排序方式

服务层

当你的Controller接收到参数时,会调用MyPage.create(page, limit, sortStr)来实现动态拼接SQL. 先来看MyPage类:

/**
* PageReqeust :工厂模式,作用是生产MyPage对象
*/
public class MyPage extends PageRequest {
    // 构造方法
    public MyPage(int page, int size, String sort) {
        super(page, limit, sort);
    }
    // 静态方法,创建MyPage对象
    public static MyPage create(Integer page, Integer size, String sort) {
        return new MyPage(page, size, sort);
    }

    public RowBounds getRowBounds() {
    // 使用PageBounds这个对象来控制结果的输出
        PageBounds bounds = new PageBounds(this.getPageNumber() + 1, this.getPageSize(), PageOrder.formString(this.getSort()), true);
        return bounds;
    }
}

/**
* MyPage对象工厂
* Pageable 接口定义 常规的分页方法
*/
public class PageRequest implements Pageable, Serializable{
    private int page;
    private int size;
    private String sort;

    public PageRequest(int page, int size, String sort) {

        if (page < 0) {
            throw new IllegalArgumentException("Page index must not be less than zero!");
        }

        if (size < 1) {
            throw new IllegalArgumentException("Page size must not be less than one!");
        }

        this.page = page;
        this.size = size;
        this.sort = sort;
    }
    // 省略上面三个属性的get方法
}

public class PageBounds extends RowBounds implements Serializable {
     public PageBounds(int page, int limit, List<PageOrder> orders, boolean containsTotalCount) {
        this.page = page;
        this.limit = limit;
        this.orders = orders;
        this.containsTotalCount = containsTotalCount;
    }
}

上面的PageOrder.formString方法代码就省略了, 主要是对参数”sort:字段名称(别名).排序方式”的解析并重新组合

拼接SQL

这段代码是公司大牛写的,把关键的部分贴出来,毕竟还是有”版权”尊重之说的.

public class SQLServer2005Dialect extends Dialect {
    protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
        StringBuffer pagingBuilder = new StringBuffer();
        String orderby = getOrderByPart(sql);
        String distinctStr = "";

        String loweredString = sql.toLowerCase();
        String sqlPartString = sql;
        if (loweredString.trim().startsWith("select")) {
            int index = 6;
            if (loweredString.startsWith("select distinct")) {
                distinctStr = "DISTINCT ";
                index = 15;
            }
            sqlPartString = sqlPartString.substring(index);
        }
        pagingBuilder.append(sqlPartString);

        // if no ORDER BY is specified use fake ORDER BY field to avoid errors
        if (orderby == null || orderby.length() == 0) {
            orderby = "ORDER BY CURRENT_TIMESTAMP";
        }

        StringBuffer result = new StringBuffer();
        result.append("WITH query AS (SELECT ").append(distinctStr).append("TOP 100 PERCENT ")
                .append(" ROW_NUMBER() OVER (").append(orderby).append(") as __row_number__, ").append(pagingBuilder)
                .append(") SELECT * FROM query WHERE __row_number__ > ? AND __row_number__ <= ?")
                .append(" ORDER BY __row_number__");
        setPageParameter(offsetName, offset, Integer.class);
        setPageParameter("__offsetEnd", offset + limit, Integer.class);
        return result.toString();
    }

    static String getOrderByPart(String sql) {
        String loweredString = sql.toLowerCase();
        int orderByIndex = loweredString.indexOf("order by");
        if (orderByIndex != -1) {
            // if we find a new "order by" then we need to ignore
            // the previous one since it was probably used for a subquery
            return sql.substring(orderByIndex);
        } else {
            return "";
        }
    }

}

自此, 在SpringMVC使用MyBatis-paginator分页插件的方法介绍就先到这了.任重而道远呐,呵呵.

写在后面的一些话

但管努力,莫问前程,相信功不唐捐

 类似资料: