At the beginning of the project, I needed to use mybatis paging. I read a lot of plug-ins online. In fact, the implementation principles are basically the same, but most of them only give code and have incomplete annotations. So I referred to many articles (each article steals a little code, evaluates my own, and semi-plagiarizes it), and then I imitated and wrote a paging plug-in suitable for my project. Without further ado, I just uploaded the code. Compared with most articles, the annotations are very complete.
The most important interceptor
package com.dnkx.interceptor; import java.sql.*; import java.util.HashMap; import java.util.Properties; import org.apache.ibatis.executor.resultset.ResultSetHandler; 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.MetaObject; import org.apache.ibatis.reflection.SystemMetaObject; import com.dnkx.pojo.Page; /** * * Pagination interceptor, used to intercept operations that require paging query and then paginate them. * The principle of Mybatis paging is implemented using interceptors: * To use JDBC to operate on the database, you must have a corresponding Statement object. Before Mybatis executes the Sql statement, it will generate a Statement object containing the Sql statement, and the corresponding Sql statement* is generated before the Statement, so we can start with the Sql statement used to generate the Statement before it generates the Statement. In Mybatis Statement statement is generated by the * prepare method of the RoutingStatementHandler object. Therefore, one of the ideas for using an interceptor to implement Mybatis paging is to intercept the prepare method of the StatementHandler interface, and then change the Sql statement into the corresponding pagination query Sql statement in the interceptor method, and then call the prepare method of the * StatementHandler object, that is, call invocation.proceed(). * For pagination, one of the operations we need to do in the interceptor is to count the total number of records that meet the current conditions. This is by obtaining the original Sql statement, changing it to the corresponding statistical statement, and then replacing the parameters in the Sql statement using the Mybatis encapsulated parameters and setting * parameters. Then, the Sql statement querying the number of records is executed to count the total number of records. * * Explain several classes that may be used in the plug-in: * MetaObject: A class provided by mybatis based on an object that returns the property value* BoundSql: In this, you can get the SQL to be executed and the parameters to be used to execute SQL* MappedStatement: This can get the value of the id configured in the XML file of the currently executed SQL statement* RowBounds: It is used for mybatis memory paging. * ParameterHandler: It is used in mybatis to replace the value that appears in SQL. * * @author Li Xiaogui November 9, 2016 10:59:04 */ @Intercepts({ @Signature(type=StatementHandler.class, method="prepare",args={Connection.class}), @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class}) }) public class PageInterceptor implements Interceptor{ //Intercept the paging keyword private static final String SELECT_ID="page"; //The code run by the plug-in will replace the original method and rewrite the most important intercept @Override public Object intercept(Invocation invocation) throws Throwable { if (invocation.getTarget() instanceof StatementHandler) { //Here we have a setting if the query method contains Page, paging other methods will ignore //So you need to get the method name StatementHandler statementHandler=(StatementHandler)invocation.getTarget(); MetaObject metaObject=SystemMetaObject.forObject(statementHandler); MappedStatement mappedStatement=(MappedStatement)metaObject.getValue("delegate.mappedStatement"); String selectId=mappedStatement.getId(); String methodName=selectId.substring(selectId.lastIndexOf(".")+1).toLowerCase(); // Then judge if Page is included, get sql if(methorName.contains(SELECT_ID)){ BoundSql boundSql=(BoundSql)metaObject.getValue("delegate.boundSql"); //Pagination parameter is a property of parameterObject parameterObject String sql=boundSql.getSql(); System.out.println("get sql:"+sql); HashMap<String, Object> map=(HashMap<String, Object>)(boundSql.getParameterObject()); //Page page=(Page)(boundSql.getParameterObject()); Page page=(Page)map.get("page"); // Rewrite sql String countSql=concatCountSql(sql); String pageSql=concatPageSql(sql,page); // System.out.println("Rewrite count sql :"+countSql); System.out.println("Rewrite select sql :"+pageSql); Connection connection = (Connection) invocation.getArgs()[0]; PreparedStatement countStmt = null; ResultSet rs = null; int totalCount = 0; try { countStmt = connection.prepareStatement(countSql); rs = countStmt.executeQuery(); if (rs.next()) { totalCount = rs.getInt(1); } } catch (SQLException e) { System.out.println("Ignore this exception"+e); } finally { try { rs.close(); countStmt.close(); } catch (SQLException e) { System.out.println("Ignore this exception"+e); } } metaObject.setValue("delegate.boundSql.sql", pageSql); //Bind count page.setNumCount(totalCount); } } return invocation.proceed(); } // Intercept the type StatementHandler, override the plugin method @Override public Object plugin(Object target) { if (target instanceof StatementHandler) { return Plugin.wrap(target, this); }else { return target; } } @Override public void setProperties(Properties properties) { } //Renovate sql public String concatCountSql(String sql){ //StringBuffer sb=new StringBuffer("select count(*) from "); /*sql=sql.toLowerCase(); if(sql.lastIndexOf("order")>sql.lastIndexOf(")")){ sb.append(sql.substring(sql.indexOf("from")+4, sql.lastIndexOf("order"))); }else{ sb.append(sql.substring(sql.indexOf("from")+4)); }*/ StringBuffer sb=new StringBuffer(); sql=sql.toLowerCase(); if(sql.lastIndexOf("order")>0){ sql=sql.substring(0,sql.indexOf("order")); } sb.append("select count(*) from ("+sql+") tmp"); return sb.toString(); } public String concatPageSql(String sql,Page page){ StringBuffer sb=new StringBuffer(); sb.append(sql); sb.append(" limit ").append(page.getPageBegin()).append(" , ").append(page.getPageSize()); return sb.toString(); } } Page class [java] view plain copypackage com.dnkx.pojo; import java.util.HashMap; import java.util.Map; /** * * Pagination query auxiliary class* @author Li Xiaogui November 9, 2016 13:55:37 */ public class Page { //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pageCurrentPage;//How many pages are private int pageBegin;//Start position private int numCount;//Total number of private int pageTotal;//Total number of private String orderField = "";//Controll the private String orderDirection displayed on the sorting page = ""; public Page(){ } public Page(int pageSize, int pageCurrentPage) { super(); this.pageSize = pageSize; this.pageCurrentPage = pageCurrentPage; } public Page(Map<String, String> map){ if(map.get("pageNum")!=null){ this.setPageCurrentPage(this.pageCurrentPage = Integer.parseInt(map.get("pageNum")));//Num of pages to query}else{ this.setPageCurrentPage(1);//Set the initial value} if(map.get("numPerPage")!=null){ this.setPageSize(Integer.parseInt(map.get("numPerPage")));//Num of displayed entries per page}else{ this.setPageSize(5);//Set the initial value} if(map.get("orderField")!=null){ this.setOrderField(map.get("orderField")); } if(map.get("orderDirection")!=null){ this.setOrderDirection(map.get("orderDirection")); } } public int getPageCurrentPage() { return pageCurrentPage; } public void setPageCurrentPage(int pageCurrentPage) { this.pageCurrentPage = pageCurrentPage; } public int getNumCount() { return numCount; } public void setNumCount(int numCount) { this.numCount = numCount; } public int getPageTotal() { return (numCount%pageSize>0)?(numCount/pageSize+1):(numCount/pageSize); } public void setPageTotal(int pageTotal) { this.pageTotal = pageTotal; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getPageBegin() { return pageSize*(pageCurrentPage-1); } public void setPageBegin(int pageBegin) { this.pageBegin = pageBegin; } public String getOrderField() { return orderField; } public void setOrderField(String orderField) { this.orderField = orderField; } public String getOrderDirection() { return orderDirection; } public void setOrderDirection(String orderDirection) { this.orderDirection = orderDirection; } public static Page getPage(int pageSize, int pageCurrentPage){ return new Page(pageSize,pageCurrentPage); } public static Page getPage(Map map){ return new Page(map); } }Call method in Controller
public String list(HttpServletRequest request) { long a=System.currentTimeMillis(); HashMap<String,Object> map=GetRequestMap.getMap(request);//Encapsulate the method yourself, take the parameter of the request Page page= Page.getPage(map);//Initialize page map.put("page", page);//Put the page object into the parameter set (this map is used by mybatis, including query conditions, sorting, pagination, etc.) //Control map.put(map.get("orderField")+"", map.get("orderDirection")); List<Employee> list=employeeService.getListPage(map); request.setAttribute("emlist", list); request.setAttribute("page", page); request.setAttribute("map", map); //Get page related attributes page.getNumCount(); //Total number of pages page.getPageTotal(); //Total number of pages long b=System.currentTimeMillis(); System.out.println("--------------Time-consuming:"+(ba)+"ms"); return "basic/employee_list"; }Finally, configure the plug-in in spring
<bean id="PageInterector"></bean> <!-- spring and MyBatis are perfectly integrated, and there is no need for mybatis configuration mapping file --> <bean id="sqlSessionFactory"> <property name="dataSource" ref="dataSource" /> <!-- Automatic scanning of mapping.xml files --> <property name="mapperLocations" value="classpath:com/dnkx/mapping/*.xml"></property> <property name="plugins"> <ref bean="PageInterector"/> </property> </bean>
OK, that's the end, this article is for reference only! Looking forward to the great god's advice