项目之前都是一次性加载所有数据,在前端对数据进行分页搜索排序功能的;如果数据量不是很多的话这样的确很方便,当数据很大时,一次性加载这么多数据会很耗时,严重影响用户体验,此时就必须采用DataTable的服务端查询了。
首先要配置Mybtis分页插件PageHelper,在Spring配置文件中配置,如下图:
我用的数据库是sqlserver,如果是mysql,helperDialect的值改成mysql即可
helperDialect=sqlserver
reasonable=true
supportMethodsArguments=true
params=count=countSql
autoRuntimeDialect=true
这里需要注意下,网上其他类似的文章配置的类是com.github.pagehelper.PageHelper,我这里是PageInterceptor,这是因为Mybatis插件必须实现Interceptor接口,低版本的PageHelper插件是PageHelper实现了,高版本是PageInterceptor,我用的是最新的5.1.4,建议大家用最新的。
前端DataTable初始化代码如下:
这里关键是要有:serverSide:true,表示开启服务端查询;
vm.tableObject = $("#element").DataTable({
columnDefs: [//列属性
{"orderable": false, "targets": 0}//不排序
],
order: [1,"desc"],
serverSide:true, //开启服务端查询
"processing": true,
ajax: {//后台交互
url: "getLog",
type: 'post',
dataType: "json",
error:backToLogin,
},
scrollX: true,//增加横向滚动条
columns: [//字段
{
data: "logId",
createdCell: function (td, cellData, rowData, row, col) {
$(td).html("");
}
},
{data: "userName"},
{data: "contents"},
{data: "operateTime"}
],
language: DTLanguage,
dom: "
这样每次查询DataTable都会自动发送很多参数给后台,打开开发者模式可以看到很多参数:
为了完美支持DataTable服务端查询,还需要DataTablePageUtil这个工具类,百度就行。
项目中还用到了PageData工具类,该类是个Map,可以充当实体类和HttpServletRequet,为此重写了DataTablePageUtil的构造器,如下:
public DataTablePageUtil(PageData pd) {
//开始的数据行数
String start = pd.getString("start");
//每页的数据数
String length = pd.getString("length");
//DT传递的draw:
String draw = pd.getString("draw");
this.setStart(Integer.parseInt(start));
this.setLength(Integer.parseInt(length));
this.setDraw(Integer.parseInt(draw));
//计算页码
this.page_num = (Integer.parseInt(start) / Integer.parseInt(length)) + 1;
this.page_size=Integer.parseInt(length);
}
后端控制器代码如下:
@RequestMapping("/getLog")
@ResponseBody
public JSONObject listAll() {
PageData pd=new PageData();
pd=this.getPageData();
DataTablePageUtil dataDataTablePageUtil=new DataTablePageUtil<>(pd);
String i =pd.getString("order[0][column]");
String fieldName=pd.getString("columns["+i+"][data]");
String dir=pd.getString("order[0][dir]");
String orderBy=fieldName+" "+dir;
PageHelper.startPage(dataDataTablePageUtil.getPage_num(),dataDataTablePageUtil.getPage_size(),orderBy);
try {
List logs=logService.listAll(pd);
//int totals=logService.getTotalCount();
//PageInfo类封装数据,提高分页性能
PageInfo pageInfo=new PageInfo<>(logs);
//封装数据给DataTables
dataDataTablePageUtil.setDraw(dataDataTablePageUtil.getDraw());
dataDataTablePageUtil.setData(pageInfo.getList());
dataDataTablePageUtil.setRecordsTotal((int) pageInfo.getTotal());
dataDataTablePageUtil.setRecordsFiltered(dataDataTablePageUtil.getRecordsTotal());
} catch (Exception e) {
e.printStackTrace();
dataDataTablePageUtil.setError("查询出错");
}
JSONObject jsonObject= (JSONObject) JSONObject.toJSON(dataDataTablePageUtil);
return jsonObject;
}
这里最关键的代码是
PageHelper.startPage(dataDataTablePageUtil.getPage_num(),dataDataTablePageUtil.getPage_size(),orderBy);
前两个参数是起始页和每页数据条数,最后一个参数是形如:字段名+desc/asc,PageHelper根据这个来重写sql增加order by语句来实现按指定列排序;
有时点击表头排序是,后台会报某列不明确的错误,网上查了下说是多表连接查询时,多个表中有相同字段名,平时单独运行sql时加个表别名前缀就行,用了PageHelper的话加了前缀还是会报错;我的解决办法是在后台做判断重写字段名;
比如,报pName字段不明确,我就这么写:
if(fieldName.equals("pName")){
fieldName="c.pName";
}
如果用的是低版本的PageHelper还有可能报某字段无效的错(这也是我一开始为什么建议使用高版本的原因),解决办法是一样的,如果有人有更好的办法可以留言告诉我
模糊查询我用的是Mybatis的方法
AND
contents LIKE concat('%',#{contents},'%')
没有和Datatable关联,DataTablePageUtil这个类中有相应属性来配合Datatable实现模糊查询,有兴趣的朋友可以自己研究下
效果如下,总数居639条,当前页10条数据
查看后台显示,发现sql已经被PageHelper插件重写了,只选出当前页的10条数据,没有全部选出
修改每页显示25条后,后台如下,说明服务端分页查询成功
点击事件列,自动按该列排序,再次点击可以在该列降序升序之间切换,查看后台发现重写的sql多了order by 语句