Most systems require analysis capabilities. This is usually done with physical paging, such as when we use a relational database, using paging parameters provided by SQL statements (such as MySQL’s limit parameter). However, the paging parameters of SQL statements vary from relational database to relational database, so there are some frameworks that provide generic paging capabilities that mask the paging methods of different databases. In the use of MyBatis database operation in the WEB system, we can use PageHelper plug-in to easily achieve support for various database paging function. You can visit GitHub at github.com/pagehelper/… .

All of the projects I’ve worked on so far use the PageHelper plugin for paging. Debugging PageHelper source code can know that it is based on MyBatis interceptor function extension implementation. However, this article is about a small problem with using PageHelper in the project, which is documented here.

The problem code

@GetMapping("/users")
public PageInfo<UserDTO> listUsers(@RequestParam int pageNum, 
                                   @RequestParam int pageSize,
                                   @RequestParam String user,
                                   @RequestParam String phone) {
    // Turn on paging
    PageHelper.startPage(pageNum, pageSize);
    // Query the user information list with multiple conditions
    List<User> users = userService.list(user, phone);
    // Process users and return the required information
    List<UserDTO> userDTOs = convertUser(users);
    // Wrap users to return paging and data information
    return newPageInfo(userDTOs); }/** * returns the information needed in users. Other fields do not return */
public List<UserDTO> convertUser(List<User> users) {
    List<UserDTO> userDTOs = new ArrayList<>();
    if(users ! =null && !users.isEmpty()) {
        users.foreach(user -> {
            UserDTO userDTO = new UserDTO();
            userDTO.setUserName(user.getUserName);
            userDTO.setPhone(user.getPhone);

            userDTOs.add(userDTO);
        });
    }
    return userDTOs;
}Copy the code

Note: To turn on paging, you must use PageHelper.startPage(pageNum, pageSize); Moreover, only the first query following this statement is paginated.

The query results

PostMan is used to query the interface. The following screenshot is displayed:

PageNum =1&pageSize=1 Query result



PageNum =1&pageSize=10 Query result



In the previous two queries, the paging parameter in Figure 1 results in a problem. For example, count is the same as currentCount, and pages is 1. This is clearly not true. Count = 3, currentCount = 1, pages = 2;

Analyze the real type of users

List<User> users = userservice. List (userName, phone); The return value Users is not actually an instance of ArrayList, because paging is turned on, so Users is an instance of the Page class in the PageHelper plug-in. So the return value can be received with Page (note: not with PageInfo)

Page<User> users = userService.list(user, phone); The return value can be received with Page<User>Copy the code

PageHelper plugin is implemented through MyBatis interceptor mechanism, the following is PageHelper interceptor page query logic:



runtimeDialect.afterPage(resultList, parameterObject, rowBounds); The code is as follows:



Figure performing a paging query executor.query(……) The resulting resultList is placed in a Page object, page. AddAll (pageList); The Page class in PageHelper is derived from the ArrayList class. Finally, the page is assigned to the Users reference in the code (cast via Object).

Error cause analysis

The real type of Users analyzed above is an instance of the Page class. So when the convertUsers(Users) method is called, the page-related parameter information is lost. The return value userDTOs is no longer an instance of Page. UserDTOs is just a normal ArrayList instance with no page-related parameter information, such as count, Pages, etc. New PageInfo(userDTOs)



That is, userDTOs is an instance of a Collection subclass, so the logic in the red box is executed, which results in the error results in our previous two queries.

The solution

Create a New PageInfo object and set the paging parameters and the data to be rebuilt into the new PageInfo object. The code is as follows:

@GetMapping("/users")
public PageInfo<UserDTO> listUsers(@RequestParam int pageNum, 
                                   @RequestParam int pageSize,
                                   @RequestParam String user,
                                   @RequestParam String phone) {
    // Turn on paging
    PageHelper.startPage(pageNum, pageSize);
    // Query the user information list with multiple conditions
    List<User> users = userService.list(user, phone);
    PageInfo<UserDTO> userDTOPageInfo = PageInfoUtil.pageInfo2PageInfo(new PageInfo(users));    // Handle users and set it to userDTOPageInfo
    convertUser(users, userDTOPageInfo);
    // Wrap users to return paging and data information
    returnuserDTOPageInfo; }/** * returns the information needed in users. Other fields do not return */
public List<UserDTO> convertUser(List<User> users, PageInfo<UserDTO> userDTOPageInfo) {
    List<UserDTO> userDTOs = new ArrayList<>();
    if(users ! =null && !users.isEmpty()) {
        users.foreach(user -> {
            UserDTO userDTO = new UserDTO();
            userDTO.setUserName(user.getUserName);
            userDTO.setPhone(user.getPhone);
            
            // Put the new data into userDTOPageInfo
            userDTOPageInfo.getList().add(userDTO);        });
    }
    returnuserDTOPageInfo; }Copy the code

Public class PageInfoUtil {/** * pageInfo object conversion generic method * P: input type V: Public static <P, V> PageInfo<V> PageInfo2PageInfoVo(PageInfo<P> pageInfoPo) {public static <P, V> PageInfo2PageInfoVo(PageInfo<P> pageInfoPo) { Page<V> Page = new Page<>(pageInfopo.getPagEnum (), pageInfopo.getPagesize ()); // Set the total number of records page.setTotal(pageinfopo.getTotal ()); PageInfo PageInfo = new PageInfo<>(page); Pageinfo.setsize (pageinfopo.getList ().size());returnpageInfo; }}Copy the code


Article history

Talk about the plug-in design of MyBatis

How is MyBatis plugin object created

Custom MyBatis interceptor, enabling business