mybatis分页

Mybatis使用分页

对这块的了解不是那么深,所以在这里需要来做一个详细的说明。了解背后的原理,来总结一下这里的东西,我觉得非常有用。

我们可以查询出来所有的数据,但是页面上肯定不会直接展示出来一页数据,所以需要来进行分页查询。

关于分页查询,点击页面的时候,首先肯定是先有“无条件”查询,然后再有根据页面上的选择框来进行有条件查询的。无条件查询是没有用户输入的参数;有条件查询是有用户输入的参数;

所以这里可以总结出来,肯定是有一个对应的实体类来进行封装的。对应的类:

public class QueryPageBean implements Serializable{
    private Integer currentPage;//页码
    private Integer pageSize;//每页记录数
    private String queryString;//查询条件
    // getter/setter
}    

这里的搜索框比较简单,用的就是一个string类型的参数,当然也可以写一个实体类来进行封装。

“无条件”查询和有条件查询,对于无条件查询来说,首先应该具备的两个参数,currentPage和pageSize这两个参数是默认的。当然也可以来写死,也是可以的。无非就是多了一个条件而已。

使用post方式:因为传递的是多个参数,需要来进行@RequestBody来进行封装条件

那么后台需要做的事情是:根据条件查询出来的总数据,最终也需要在页面上来进行显示。那么应该有总条数+条件查询记录

至于分页的事情,应该交给前端来做。

分页请求参数:currentPage+pageSize (无条件查询),currentPage+pageSize +queryString (有条件查询) QueryPageBean类

分页响应结果:total(条件查询的总记录数)+rows(条件查询当前页面需要显示的数据集合) PageResult类

但是最终都需要通过Result类来响应出去,分页的操作交给PageHelper分页插件来操作;

PageHelper插件使用:

1、引入分页插件;

2、配置分页插件;

3、在Service层中使用:

a.

PageHelper.startPage(1,10);

b.需要来写分页查询的语句(SQL语句中不必写limit关键字)

c.在ab两步中间不要写任何的代码。返回结果对象Page分页对象,分页插件提供的。

d.从page对象中获取得到total、rows的值。

正确使用方式:

接口层:

    //分页查询
    @RequestMapping("findPage")
    public PageResult findPage(@RequestBody QueryPageBean queryPageBean){
        PageResult pageResult = checkItemService.pageQuery(
                queryPageBean.getCurrentPage(),
                queryPageBean.getPageSize(),
                queryPageBean.getQueryString());
        return pageResult;
    }

service层:

    @Override
    public PageResult pageQuery(Integer currentPage, Integer pageSize, String queryString) {
        PageHelper.startPage(currentPage,pageSize);
        Page<CheckItem> page = checkItemDao.selectByCondition(queryString);
        return new PageResult(page.getTotal(),page.getResult());
    }

dao:

Page<CheckItem> selectByCondition( String queryString);

对应的xml文件:

    <select id="selectByCondition" parameterType="string" resultType="com.itheima.pojo.CheckItem">
        select * from t_checkitem
        <if test="condition != null and condition.length > 0">
            where code = #{value} or name = #{value}
        </if>
    </select>

那么重点分析一下servcie层的两条语句:

PageHelper.startPage(currentPage,pageSize);
Page<CheckItem> page = checkItemDao.selectByCondition(queryString);

看一下startPage中的方法,最终会来到com.github.pagehelper.PageHelper

public class PageHelper implements Interceptor
    public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {
        Page<E> page = new Page(pageNum, pageSize, count);
        page.setReasonable(reasonable);
        page.setPageSizeZero(pageSizeZero);
        Page<E> oldPage = SqlUtil.getLocalPage();
        if (oldPage != null && oldPage.isOrderByOnly()) {
            page.setOrderBy(oldPage.getOrderBy());
        }
		// 来到了这里!!
        SqlUtil.setLocalPage(page);
        return page;
    }

看一下具体的实现:

private static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal<Page>();    
public static void setLocalPage(Page page) {
        LOCAL_PAGE.set(page);
    }

可以看到这里使用ThreadLocal类来进行修饰的,所以这里应该会有get和remove方法来进行调用,在当前类中可以看到:

    public static void clearLocalPage() {
        LOCAL_PAGE.remove();
    }

    public static <T> Page<T> getLocalPage() {
        return LOCAL_PAGE.get();
    }

那么为什么需要下面两个语句在一起使用?

PageHelper.startPage(currentPage,pageSize);
Page<CheckItem> page = checkItemDao.selectByCondition(queryString);

不妨从clearLocalPage这个方法来入手,因为执行完selectByCondition应该会立刻执行clearLocalPage操作。

如果中间有对应的SQL查询语句,那么将会使得查询的时候,不会来拼接limit ?,?来进行拼接了,因为上一条SQL语句执行完成之后会将ThreadLocal中的数据给清除掉。

不妨用案例来进行演示一下:

    @Override
    public PageResult pageQuery(Integer currentPage, Integer pageSize, String queryString) {
        PageHelper.startPage(currentPage,pageSize);
        System.out.println("hello,world");
        Page<CheckItem> page = checkItemDao.selectByCondition(queryString);
        return new PageResult(page.getTotal(),page.getResult());
    }

如上操作,添加输出语句!分页操作不受任何影响。

接着测试:

    @Override
    public PageResult pageQuery(Integer currentPage, Integer pageSize, String queryString) {
        PageHelper.startPage(currentPage,pageSize);
        List<CheckItem> checkItemList = checkItemDao.findAll();
        Page<CheckItem> page = checkItemDao.selectByCondition(queryString);
        return new PageResult(page.getTotal(),page.getResult());
    }

这里就有了问题!因为findAll这条SQL执行完成之后,会将ThreadLocal中的变量给清除掉,导致后面的找不到对应的线程变量

可以看到selectByCondition的方法执行,会来进行获取,但是没有获取得到,那么就会去查询所有的语句!

posted @ 2022-01-03 22:33  雩娄的木子  阅读(202)  评论(0编辑  收藏  举报