一般分页有分页插件,排序在sql指定字段就好,但是最近我遇到一种情况,就是sql语句比较复杂。。有八十多行,两张表(7w 和 11w)数据不算多,但是sql语句嵌套的有点厉害,我特意试了试,那个sql跑完要花1.3w+秒。。。项目里用那个sql肯定不行,然后就把sql简化了,作为了四个查询单表的sql,这样的话就没有嵌套了,但是这样也导致所有的逻辑业务要在serviceImpl里处理了。。而且还不能用分页插件和指定排序字段。。业务逻辑我就不和大家bb了,说说逻辑分页和排序 的思路。
首先排序:
Collections.sort(underList), Collections有个排序的方法,sort里面放的就是排序字段。另外,还需要让underList字段对应的对象实现Comparable接口,这是一个比较器接口。例如:
public class Undercarriage implements Serializable,Comparable<Undercarriage>
该对象就实现了序列化接口和比较器接口两个接口,然后在该对象里面重写它的compareTo方法:
@Override public int compareTo(Undercarriage o) { //return this.underRate.compareTo(o.underRate); if(o.underRate == null){ o.underRate = 0.0; } if(this.underRate == null){ this.underRate = 0.0; } return o.underRate.compareTo(this.underRate); }
其中那两个if是我为了防止判断的时候出现空指针异常自己加的,return的才是重点,compareTo比较的是其前后的数据,就是排序实现的具体依据,至于排出来的是倒序还是正序,只需要换compareTo前后的对象就好,自己多试试就知道了。
逻辑分页:
首先一个page的扩展类肯定是需要的
public class Page { // 当前页 private Integer pageIndex; // 每页条数 private Integer pageSize; // 开始记录 @SuppressWarnings("unused") private Integer pageStart; // null或者0分页;1:不分页 private Integer all; private String startdate; private String enddate; // 排序字段 private String sortField; // desc or asc private String orderType; }然后,写一个for循环:
//分页 Integer size=underList.size(); Integer pageSize = pvo.getPageSize(); //页数 for (int i = 1; i <= (size%pageSize == 0 ? (size/pageSize) : ((size/pageSize)+1) ); i++) { synchronized (key) { String key1 = i + "selectUnderRate" + pageSize; subList = new ArrayList<>(underList.subList((i - 1) * pageSize, pageSize*i <= size ? pageSize*i:size )); redis.setex(key1, 600, SerializeUtil.serialize(Message.success(subList))); } }其中,我这里的i其实是和pageIndex(当前页)是一个意思的,我这里的意思就是说,把最后得出的数据集合underList按页数和每页放的条数加上我这个接口的方法名作为了key,存到了redis缓存里,这样下次用户再访问的时候,数据就能从缓存中取出从而大大加快查询的效率了。其中,for循环里i的循环条件大家要注意下,我用的三目运算符以保证i最大的数值可以和分的页数相等。然后最后按照他传入的pageIndex和pageSize返回对应的数据:
Integer i=pvo.getPageIndex(); subList = new ArrayList<>(underList.subList((i - 1) * pageSize, pageSize*i <= size ? pageSize*i:size ));后面记得返回subList的数据就好,之后pageIndex和pageSize没变的话,我们都可以从缓存中拿数据,能加快不少速度。另外我这里所用的截取都是直接三目运算符判断的,大家也可以提取出来。然后,提醒下subList()这个函数截取的数据是集合的索引作为截取标的,并且是左包含右不包含的。
好了,大致的思路就是这样了,其实为了加快速度,最好把这个接口放到定时任务里去,让他自己按时跑一跑查询数据, 我们全部从缓存里拿取最好。大家想看的的话,可以看我上一篇的定时任务的实现篇。然后这其中有什么不懂得,都可以留言问我。