最近公司任务比较紧(为自己懒没写博客找的理由还不错), 关于博客的更新停滞了一段时间.最近一直在”仔细揣摩”公司项目的各种历史存储过程,那个苦啊,看的整个人不行不行的,关键是还得把诸如此类的存储过程改成java代码,还得自己写各种测试用例,对于我这种刚进公司的业务小白来说,实在是有点那啥了…
言归正传,幸好我们组长看我做事比较认真,最近交给我一个”光荣使命”:给公司分页插件添加一个支持字段排序的小功能(其实就是动态给业务SQL加上order by的东西),还好幸不辱命,还得以一窥 MyBatis-paginator 插件的其他使用,特意总结下,分享给寥寥无几的数人…
MyBatis-paginator 是github上的一个开源项目, 主要作用就是从java后台获取分页数据,并结合另外一个基于jQuery的表格控件:mmgrid用于展示后台分页数据.
开源项目地址为: https://github.com/miemiedev
<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
@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中使用分页插件的写法:
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:字段名称(别名).排序方式”的解析并重新组合
这段代码是公司大牛写的,把关键的部分贴出来,毕竟还是有”版权”尊重之说的.
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分页插件的方法介绍就先到这了.任重而道远呐,呵呵.
但管努力,莫问前程,相信功不唐捐