PageHelper使用ThreadLocal来记录分页申明,并修改后续mybatis mapper执行逻辑。线程池和ThreadLocal引发的问题,比较难以定位,特此记录:
一、询结果行数不准确
在http、dubbo处理线程上,调用PageHelper.startPage后,如果不立即执行mapper的查询方法而发生了异常,退出当前请求的处理;由于线程复用,ThreadLocal里的分页申明记录将影响线程将来处理新请求时调用的某个未知mapper,给查询语句强行增加limit限制,从而返回局部结果。
二、处理查询结果List时,抛出ClassCastException
如果使用PageHelper.startPage仅仅为了初始化一个Page容器来装载数据,则装载的数据会遗留在ThreadLocal里,影响下个查询语句的结果:
@Test
public void testPaging() throws Exception {
Page<Person> page = PageHelper.startPage(1, 10);
Person aPerson = new Person();
page.add(aPerson);
List<UserInfo> lst = userMapper.query();
// mapper方法的返回结果,就是一开始进行分页申明时得到的page对象
assertTrue(lst == (Object) page);
// 查询结果List的第一个数据,实际是之前插入到page里的数据,类型并不是UserInfo
assertTrue(lst.get(0) == (Object) aPerson);
}
当使用for循环获取上述的lst里的数据对象时,就会触发ClassCastException