Introduction

Paging and sorting are two of the basic functions provided by databases.

For example, a typical SQL query statement in MySQL is as follows:

SELECT * FROM t_user
ORDER BY create_time DESC, username ASC
LIMIT 10 OFFSET 20

Then, how should the frontend pass the parameters of paging and sorting to the backend? What parameters need to pass? What is the meaning and format of the parameters?

Paging

The paging statement is LIMIT 10 OFFSET 20, where 10 is the size of each page, and 20 is the offset of the query, that is, the 21st to 30th items in the query table, 10 pieces of data totally.

However, when designing the interface, the frontend is usually not required to directly pass in the OFFSET parameter. In fact, the value of OFFSET is calculated by passing in the page number and page size.

In this case, assuming that the frontend page number starts from 1, the data to be queried is the data on the third page with a page size of 10, and the corresponding OFFSET value is calculated as (3-1)*10 = 20.

When the frontend calls the backend query interface, it usually passes in the page number and the size of each page, and the backend calculates OFFSET to do paging query. Here, the parameter name of the page number is defined as pageNumber, and the parameter name of the page size is defined as pageSize, and assuming that the page number starts from 1, then the calculation formula of OFFSET would be:

(pageNumber - 1) * pageSize

Then the frontend should pass the parameters like this:

?pageNumber=3&pageSize=10

Paging Dialect

The paging statements for different databases are not consistent, but they generally require three parameters: SQL statement, page size and offset.

So we can define an interface Dialect for building paging statements, and provide the corresponding paging implementation according to the database used.

public interface Dialect {
    String buildPageSql(String sql, int limit, long offset);
}

Sorting

The sorting statement is ORDER BY create_time DESC, username ASC, where ORDER BY is a SQL keyword, which can be defined as a parameter name. I named it sort since it is used for sorting, and the corresponding value is create_time DESC, username ASC. The GET request needs to escape the space in the parameter value. In order to avoid this problem, we can convert the , in the value to ;, and convert the space before DESC/ASC to ,. The final parameter sent by frontend will look like this:

?sort=create_time,desc;username,asc

Request Object

Combining the above parameter definitions and descriptions for paging and sorting, the frontend values can send parameters as follows:

?pageNumber=3&pageSize=10&sort=create_time,desc;username,asc

Then we can define a class PageQuery to process paging and sorting parameters:

public class PageQuery {
    private Integer pageNumber;
    private Integer pageSize;
    private String sort;
}

Each query has explicit or implicit paging and sorting, such as:

SELECT * FROM t_user

is EQUAL to

SELECT * FROM t_user
ORDER BY id ASC
LIMIT ∞ OFFSET 0

So PageQuery should be used as the parent class of all query objects in order to provide paging and sorting capabilities for data queries.

Response Object

For the frontend paging query request, in addition to returning the corresponding data list, it also needs to return the total number of data total to help the frontend calculate the total number of pages. The calculation formula is ⌈total/size⌉. The corresponding response object is defined as follows:

public class PageList<T> {
    private final List<T> list;
    private final long total;
}

Conclusion

This article mainly introduces the object-oriented solution for paging and sorting in database queries, that's all.