关于分页的一次失败的尝试

来源:互联网 发布:全局搜索能力强的算法 编辑:程序博客网 时间:2024/05/21 10:21

工作2年,几个项目下来对现有的东西做改进似乎是顺其自然的事情。

分页查询差不多是每个项目都要用的东西,比较通用的实现方法是:直接在数据库分页,针对不同数据库,分页方式也是有所差别的。一般来说代码是这样的:(我用mysql)

/** * 查询分页信息 * @param pageInfo 分页对象中包含的对象的类信息。 * @param sql 数据库查询语句 * @param pageStart 第几页 * @param pageSize 每页多少条记录 * @param args 查询条件 * @return 分页好的分页信息 */public <T> Page<T> paginate(Class<T> pageInfo,String sql, int pageStart, int pageSize,String sort,String sortD,Object... args) {StringBuilder pageSql=new StringBuilder(128);pageSql.append(sql).append(" LIMIT ").append(pageStart).append(",").append(pageSize);if(sort!=null&&sortD!=null){//拼接排序方式pageSql.append(" order by ").append(sort).append(" ").append(sortD);}String pageCount="select count(1) "+sql.substring(sql.indexOf("from "));//替换掉from 之前的部分为select  count(1)Integer total=queryObject(pageCount, Integer.class, args);//用springTemple实现的数据库查询,执行sql,查询记录总数List<T> data= queryObjectList(pageSql.toString(), pageInfo, args);//执行sql,查询出一页的数据到集合Page<T> page=new Page<T>(data, total);return page;}

这方法也算经典吧,但若是对于同一个分页查询,只是做页面间的跳转的话获取 记录总数 的查询是不是在做重复劳动呢?为此我的一个思路是对查询语句,查询条件做hash,提取其信息摘要,以摘要为键将记录总是保存在缓存中,这个缓存最好和会话有关系,如果会话结束缓存可以得到释放。我的代码是下面这个样子:

public <T> Page<T> paginate(Class<T> pageInfo,String sql, int pageStart, int pageSize,String sort,String sortD,Object... args) {/*这种尝试是徒劳的,如果在其他地方为对应的表增加或删除了记录,这里是无法感知的,故记录总数就会停留在第一次查询且查询条件没变的样子*/String pageHash;if(args==null){//获取摘要pageHash=FrameUtils.encryptMD5(sql);}else{pageHash=FrameUtils.encryptMD5(sql, Arrays.asList(args).toString());}StringBuilder pageSql=new StringBuilder(128);pageSql.append(sql).append(" LIMIT ").append(pageStart).append(",").append(pageSize);if(sort!=null&&sortD!=null){//拼接排序方式pageSql.append(" order by ").append(sort).append(" ").append(sortD);}String pageCount="select count(1) "+sql.substring(sql.indexOf("from "));//替换掉select 与 from 之间的部分为 count(1)/*获取当前用户的会话,我用的shiro做安全框架,所以就在这里侵入一下了,有点不通用*/Session session=SecurityUtils.getSubject().getSession();Integer total;if(session.getAttribute(pageHash)!=null){/*如果找到,则不进行数据库查询*/total=(Integer)session.getAttribute(pageHash);}else{/*如果没有找到对应的值,则重新查询*/total=queryObject(pageCount, Integer.class, args);session.setAttribute(pageHash, total);}Integer total=queryObject(pageCount, Integer.class, args);List<T> data= queryObjectList(pageSql.toString(), pageInfo, args);Page<T> page=new Page<T>(data, total);return page;}

当我要实现新增删除的时候,才发现这是多么幼稚的想法,被分页的数据发生变动后,数据总数就会跟实际数据不符。若是翻到最后一页就会暴露问题所在。

作为一个通用的分页方式,这是不可取的。

     但这个方法在特殊环境下也是有用的。比如在只做查询地方,数据总数在查询的时候不发生变化就没问题。还有就是在数据量很大,且对数据分页总的显示与实际数据的匹配情况出现差异可以容忍的环境,这个都是不错的方式。

   但总的来说,我是想弄个通用的分页的新方法的,结果还是失败了,但也长进了不少。

原创粉丝点击