How to implement the paging function of MyBatis interceptor

How to implement the paging function of MyBatis interceptor

How to implement the paging function of MyBatis interceptor

Preface:

First, let’s talk about the implementation principle. Use the interceptor to intercept the original SQL, then add the keywords and attributes of the paging query, assemble them into a new SQL statement and hand it over to mybatis for execution.

In addition to the business code, there is not much to write, here are a few key ones:

1. Paging object Page class. Set two parameters for the object: the current page number (given by the front end) and the total number of records (assigned in the interceptor), and it will help you calculate the two parameters used in the paging SQL statement.

/**
 * Entity class corresponding to paging */
public class Page {
  /**
   * Total number of entries*/
  private int totalNumber;
  /**
   * Current page */
  private int currentPage;
  /**
   * Total Pages*/
  private int totalPage;
  /**
   * Number of entries per page*/
  private int pageNumber = 5;
  /**
   * The limit parameter in the database, from which entry should be taken*/
  private int dbIndex;
  /**
   * The limit parameter in the database, how many entries are taken in total*/
  private int dbNumber;

  /**
   * Calculate and set related attribute values ​​according to the attribute values ​​in the current object*/
  public void count() {
    // Calculate the total number of pages int totalPageTemp = this.totalNumber / this.pageNumber;
    int plus = (this.totalNumber % this.pageNumber) == 0 ? 0 : 1;
    totalPageTemp = totalPageTemp + plus;
    if(totalPageTemp <= 0) {
      totalPageTemp = 1;
    }
    this.totalPage = totalPageTemp;

    // Set the current page number // The total number of pages is less than the current number of pages, the current page number should be set to the total number of pages if (this.totalPage < this.currentPage) {
      this.currentPage = this.totalPage;
    }
    // If the current page number is less than 1, set it to 1
    if(this.currentPage < 1) {
      this.currentPage = 1;
    }

    //Set limit parameters this.dbIndex = (this.currentPage - 1) * this.pageNumber;
    this.dbNumber = this.pageNumber;
  }

  public int getTotalNumber() {
    return totalNumber;
  }

  public void setTotalNumber(int totalNumber) {
    this.totalNumber = totalNumber;
    this.count();
  }

  public int getCurrentPage() {
    return currentPage;
  }

  public void setCurrentPage(int currentPage) {
    this.currentPage = currentPage;
  }

  public int getTotalPage() {
    return totalPage;
  }

  public void setTotalPage(int totalPage) {
    this.totalPage = totalPage;
  }

  public int getPageNumber() {
    return pageNumber;
  }

  public void setPageNumber(int pageNumber) {
    this.pageNumber = pageNumber;
    this.count();
  }

  public int getDbIndex() {
    return dbIndex;
  }

  public void setDbIndex(int ​​dbIndex) {
    this.dbIndex = dbIndex;
  }

  public int getDbNumber() {
    return dbNumber;
  }

  public void setDbNumber(int dbNumber) {
    this.dbNumber = dbNumber;
  }
}

2. Key interceptor implementation

package com.imooc.interceptor;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.Properties;

import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

import com.imooc.entity.Page;

/**
 * Paging Blocker * 
 * @author Skye
 *
 */
@Intercepts({
    @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class }) })
public class PageInterceptor implements Interceptor {

  public Object intercept(Invocation invocation) throws Throwable {
    StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
    MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY,
        SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
    MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
    //Get the method name id through MetaObject metadata: com.XXX.queryMessageListByPage
    String id = mappedStatement.getId();
    //Match the query ID related to paging defined in mybatis
    if (id.matches(".+ByPage$")) {
      //BoundSql contains the original SQL statement and the corresponding query parameters BoundSql boundSql = statementHandler.getBoundSql();
      Map<String, Object> params = (Map<String, Object>) boundSql.getParameterObject();
      Page page = (Page) params.get("page");
      String sql = boundSql.getSql();
      String countSql = "select count(*)from (" + sql + ")a";
      Connection connection = (Connection) invocation.getArgs()[0];
      PreparedStatement countStatement = connection.prepareStatement(countSql);
      ParameterHandler parameterHandler = (ParameterHandler) metaObject.getValue("delegate.parameterHandler");
      parameterHandler.setParameters(countStatement);
      ResultSet rs = countStatement.executeQuery();
      if (rs.next()) {
        //Why getInt(1)? Because the columns of the data table start counting from 1 page.setTotalNumber(rs.getInt(1));
        System.out.println("The interceptor learns that the total number of records in the page is: " + page.getTotalNumber());
      }
      String pageSql = sql + " limit " + page.getDbIndex() + "," + page.getDbNumber();
      metaObject.setValue("delegate.boundSql.sql", pageSql);
    }
    return invocation.proceed();
  }

  /**
   * @param target
   * The object being intercepted */
  public Object plugin(Object target) {
    // If the interceptor class is likened to a company that buys tickets on behalf of others, then this is the agent who buys tickets on behalf of others (before entering the method, he is a agent without the ability to buy tickets on behalf of others, and after entering, he becomes a agent with the ability to buy tickets on behalf of others)
    // Get the information of the interception target through annotations. If it does not meet the interception requirements, return the original target. If it meets the requirements, use dynamic proxy to generate a proxy object. return Plugin.wrap(target, this);
  }

  public void setProperties(Properties properties) {
    // TODO Auto-generated method stub

  }

}

3. Register your own interceptor in mybatis-config.xml

 <!-- Customized paging interceptor-->
  <plugins>
    <plugin interceptor="The full class name of the interceptor you wrote">
    </plugin>
  </plugins>

The sql statements in the mapper.xml related to the Dao layer do not need to be changed.

4. The front end needs to give the back end a parameter of which page to display. After assembling the query parameters through the service layer, it is handed over to MyBatis to query the paging data. The data returned by the paging DAO interface I defined is a list, which contains the paging query results. The front end can use the jquery_pagination plug-in to implement pagination display. Please go to the official github to see how to set it up.

<!--Scripts required for pagination-->
<%
  // Get the request context String context = request.getContextPath();
%>
<link href="../css/pagination.css" rel="external nofollow" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../js/jquery-1.11.3.js"></script>
<script type="text/javascript" src="../js/jquery.pagination.js"></script>
<script type="text/javascript">

//Action triggered after clicking the pagination button function handlePaginationClick(new_page_index, pagination_container) {
<!--Submit the parameters of the current page from the stuForm form. You can use the restful method to let springmvc use the parameters defined by the @PathVariable keyword to connect. These two parameters are provided by the paging control itself, so we don't need to find them ourselves. However, the count starts at 0, and our background paging count starts at 1, so we need to add 1 manually. -->
  $("#stuForm").attr("action", "The paging query url you defined/"+(new_page_index+1));
  $("#stuForm").submit();
  return false;
}

$(function(){
  $("#News-Pagination").pagination(${result.totalRecord}, ​​{
    items_per_page:${result.pageSize}, // How many records are displayed per page current_page:${result.currentPage} - 1, // Which page of data is currently displayed num_display_entries:8, // Number of entries displayed in pages next_text:"Next page",
    prev_text: "Previous page",
    num_edge_entries:2, //Connect to the pagination body, the number of entries displayed callback:handlePaginationClick(current page, id of the pagination div), //Callback function executed load_first_page:false //Prevent the page from being refreshed all the time (this is very important!)
  });
});
</script>
<!-- This part uses the c:forEach tag to print the query results table-->
<!--Paging control name-->
<div id="News-Pagination"></div>

The purpose of writing this summary is to form an overall solution for paging function (covering both front-end and back-end). Starting from April 17th and 18th, I will write a small system to apply what I have learned in the past period of time. After that, I will come back to update the incorrect parts in this article.

If you have any questions, please leave a message or discuss in the community of this site. Thank you for reading. I hope it can help you. Thank you for your support of this site!

You may also be interested in:
  • Mybatis Limit implements paging function
  • Mybatis implements joint table query and paging function
  • Mybatis Plus custom method to achieve paging function sample code
  • Spring MVC+MyBatis+MySQL to implement paging function example
  • MyBatis interceptor implements paging function example
  • MyBatis explains in great detail how to implement paging

<<:  Detailed configuration of wireless network card under Ubuntu Server

>>:  Implementation of react automatic construction routing

Recommend

A commonplace technique for implementing triangles using CSS (multiple methods)

In some interview experiences, you can often see ...

JavaScript to implement random roll call web page

JavaScript writes a random roll call webpage for ...

Docker generates images through containers and submits DockerCommit in detail

Table of contents After creating a container loca...

MySQL 8.0.12 Simple Installation Tutorial

This article shares the installation tutorial of ...

Implementation of Docker cross-host network (overlay)

1. Docker cross-host communication Docker cross-h...

How to call a piece of HTML code together on multiple HTML pages

Method 1: Use script method: Create a common head...

Analysis and solution of MySQL connection throwing Authentication Failed error

[Problem description] On the application side, th...

Apache ab concurrent load stress test implementation method

ab command principle Apache's ab command simu...

A brief introduction to Linux performance monitoring commands free

When the system encounters various IO bottlenecks...

How to redirect PC address to mobile address in Vue

Requirements: The PC side and the mobile side are...

How to display the border when td is empty

Previously, I summarized how to use CSS to achieve...

Summary of methods for inserting videos into HTML pages

Now if you want to use the video tag in a page, y...

Discussion on CSS style priority and cascading order

In general : [1 important flag] > [4 special fl...