Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🧐为什么不添加支持分页的函数呢 #548

Open
DULLONEX opened this issue Apr 29, 2024 · 4 comments
Open

🧐为什么不添加支持分页的函数呢 #548

DULLONEX opened this issue Apr 29, 2024 · 4 comments

Comments

@DULLONEX
Copy link

DSL例如

data class Page(val pageNo: Int, val pageSize: Int, val totalRecords: Int, val records: Query)

fun Query.paging(pageNo: Int, pageSize: Int): Page {
    val records = this.limit(pageSize).offset((pageNo - 1) * pageSize)
    return Page(pageNo, pageSize,records.totalRecordsInAllPages, records)
}

实体类查询正如你代码所示

database.sequenceOf(Departments)
            .drop(0)
            .take(10)

为什么不去添加到框架中呢?

@asdshuaishuai
Copy link

我猜大概是不好把控关于不同人使用page从0或者从1的这个问题吧

@DULLONEX
Copy link
Author

我猜大概是不好把控关于不同人使用page从0或者从1的这个问题吧

    /**
     * 计算当前分页偏移量
     */
    default long offset() {
        long current = getCurrent();
        if (current <= 1L) {
            return 0L;
        }
        return Math.max((current - 1) * getSize(), 0L);
    }

这是mybatis-plus的IPage类的分页offset。0和1都是一样的,又不是数组主要还是得前端显示看的

@DULLONEX DULLONEX reopened this Apr 30, 2024
@li-fcb1899
Copy link

import org.springframework.data.domain.Page
import org.springframework.data.domain.PageImpl
import org.springframework.data.domain.PageRequest

fun <E : Any, T : BaseTable<E>> EntitySequence<E, T>.page(pageNo: Int, pageSize: Int): Page<E> =
    drop((pageNo - 1) * pageSize).take(pageSize).run {
        PageImpl(toList(), PageRequest.of(pageNo, pageSize), totalRecordsInAllPages.toLong())
    }

@vincentlauvlwj
Copy link
Member

分页查询可以使用 droptake 函数,计算总页数可以通过 totalRecordsInAllPages 获取到数据总量,通过这些已经可以很方便地支持分页了

缺少的只不过是一个 page 类而已,之所以不提供,是因为通常每个项目都会有自己的 page 类,如果 ktorm 也提供了这个类,实际使用中也不过是把 ktorm 提供的 page 对象转换成项目自己的 page 对象而已,白白多一层无用的转换,就算 ktorm 没有 page 类,自己写一个也很简单

比如我自己的项目里面,page 类是这样子定义的,这些类在每个公司的项目里基本都有现成的,而且形式千奇百怪,里面的字段名也没法统一

/**
 * 分页入参
 */
@Data
public class Pageable implements Serializable {
    @Serial
    private static final long serialVersionUID = 349373016373448442L;
    private int pageNo;
    private int pageSize;

    public int getStartIndex() {
        return (this.pageNo - 1) * this.pageSize;
    }
}

/**
 * 分页结果
 */
@Data
public class Paged<T> implements Serializable {
    @Serial
    private static final long serialVersionUID = -9097463620341955241L;
    private List<T> modelList;
    private int pageNo;
    private int pageSize;
    private int totalCount;

    public Paged(List<T> modelList, Pageable pageable, int totalCount) {
        this.modelList = modelList;
        this.pageNo = pageable.getPageNo();
        this.pageSize = pageable.getPageSize();
        this.totalCount = totalCount;
    }
}

最终把 ktorm 的查询结果转换成项目的 page 对象,也只需要一行代码

/**
 * ktorm 分页查询
 */
fun queryUsers(name: String, pageable: Pageable): Paged<User> {
    val users = database.users
        .filter { it.name eq name }
        .drop(pageable.startIndex)
        .take(pageable.pageSize)

    return Paged(users.toList(), pageable, users.totalRecordsInAllPages)
}

说到底,ORM 框架支持分页的核心是实现两个功能:

  1. 提供类似 drop/take 或 limit/offset 的函数,查询页面内容,ktorm 都有
  2. 提供方便的查询总记录数量的能力,让用户不必额外构造一条 count(*) 查询,这个 ktorm 用 totalRecordsInAllPages 实现了

而 page 类只不过是细枝末节而已

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants