主题:BeetlSQL PageQuery第二次调用getTotalPage的bug

Succy 2019年01月27日 112

在使用BeetlSQL的PageQuery分页查询时,通常是以下写法:

void queryByCondition(PageQuery pageQuery);
PageQuery queryByCondition(PageQuery pageQuery);

以上面第一种为例子说明;PageQuery作为参数的同时,还作为返回值的引用。废话不多说,直接看代码

public Object query(PageQuery<Actor> pageQuery) {
    // 打印以下pageQuery参数。
    String pageQueryStr = JsonUtil.toJson(pageQuery);    
    Console.log("pageStr: {}", pageQueryStr);  
  
    actorDao.queryByPage(pageQuery);  
    // 打印pageQuery的结果集  
    pageQueryStr = JsonUtil.toJson(pageQuery);    
    Console.log("pageStr: {}", pageQueryStr);   
    return pageQuery;
}

注:以上代码中的JsonUtil是封装了Jackson的ObjectMapper进行序列化。其底层应该是通过反射调用getter,由于没有阅读过Jackson源码,这里用应该说明一下,后面有用。

这样一看似乎没什么问题,但是问题出现了,可以看一下下面的打印结果:

## 这里是刚传递下来的参数打印的情况,请注意totalPage,由于一开始没有结果集,所以是1
pageStr: {"list":null,"paras":null,"orderBy":"last_name asc","pageNumber":1,"pageSize":10,"totalPage":1,"totalRow":-1,"firstPage":true,"lastPage":true}

## 这是查询之后打印出来的结果,请注意totalPage,发现还是1
pageStr: {"list":[{"tails":{"last_update":1139949273000,"last_name":"AKROYD","actor_id":182,"first_name":"DEBBIE"}},{"tails":{"last_update":1139949273000,"last_name":"AKROYD","actor_id":92,"first_name":"KIRSTEN"}},{"tails":{"last_update":1139949273000,"last_name":"AKROYD","actor_id":58,"first_name":"CHRISTIAN"}},{"tails":{"last_update":1139949273000,"last_name":"ALLEN","actor_id":194,"first_name":"MERYL"}},{"tails":{"last_update":1139949273000,"last_name":"ALLEN","actor_id":118,"first_name":"CUBA"}},{"tails":{"last_update":1139949273000,"last_name":"ALLEN","actor_id":145,"first_name":"KIM"}},{"tails":{"last_update":1139949273000,"last_name":"ASTAIRE","actor_id":76,"first_name":"ANGELINA"}},{"tails":{"last_update":1139949273000,"last_name":"BACALL","actor_id":112,"first_name":"RUSSELL"}},{"tails":{"last_update":1139949273000,"last_name":"BAILEY","actor_id":190,"first_name":"AUDREY"}},{"tails":{"last_update":1139949273000,"last_name":"BAILEY","actor_id":67,"first_name":"JESSICA"}}],"paras":null,"orderBy":"last_name asc","pageNumber":1,"pageSize":10,"totalPage":1,"totalRow":201,"firstPage":true,"lastPage":true}

仔细观察上面两次结果的totalPage字段,会发现两次都是1,很显然第二次的这个totalPage不对,因为每页10条记录,总共有201条记录,应该是有21页总页数才对。那么问题原因在哪呢?通过查阅beetlsql的PageQuery源码,不难发现,先看getTotalPage()

QQ截图20190127222421.png

发现里面调用了calcTotalPage()方法,那么再看这个方法

QQ截图20190127222359.png

到这里问题就暴露了出来了,上面说到,Jackson序列化json的时候,会调用getter,也就是说,打印出totalPage的时候,实际上是调用了getTotalPage(),也等于调用了一次calcTotalPage。第一次打印出参数的时候,调用了一次calcTotalPage()方法,this.calc就会变成了true。第二次查询结果返回时,再打印一次,同样调用getTotalPage和calcTotalPage,不同的是,在calcTotalPage里面,并不会重新计算这个totalPage的值了,而是直接return!

也就是说,调用Dao的queryByCondition()传递pageQuery下去之前,如果调用了pageQuery的getTotalPage方法的话,当结果返回给这个引用时,再调用这个方法则不能计算出正确的总页数。

闲大赋 2019年01月29日

是有点小问题,下个版本改改