Mybatis learning seven (pagination)

1. Concept of Pagination

For example, there are 1000 pieces of data in a table in the database,

We only display 100 data items at a time, and display items 0 to 99 on page 1,

Display items 100 to 199 on page 2, and so on, which is paging.

Paging can be divided into logical paging and physical paging.

Logical paging is that when our program displays the data of each page,

First, query 1000 pieces of data in the table, and then select 100 pieces of data to display according to the "page number" of the current page.

Physical paging is that the program first judges the number to which of the 1000 items should be selected,

Then, according to the information given by the program, the database queries out 100 items required by the program and returns them to our program.

 

2.MyBatis physical paging

Implement logical paging:

The paging implemented by MyBatis using rowboundaries is logical paging,

That is, first query all the data records, and then truncate the records according to offset and limit.

Physical paging

In order to realize physical paging at the database level without changing the original MyBatis function logic,

You can write a plugin to intercept the statement handler of MyBatis Executor and rewrite SQL to execute the query.

 

3. Development steps

Step 1: function description

Use the integration of MyBatis and Spring MVC to complete paging, and complete such a simple function, that is, specify a user (ID=1),

Query all orders associated with this user and display them in pages (using MySQL database)

Step 2: create a project

          Configuration.xml

           applicationContext.xml

Step 3: database table structure and data record

            

 

 

Step 4: instance object

            

 

            

 

 

Step 5: configuration file

            applicationContext.xml

            

 

           Configuration.xml

           

 

           UserMaper.xml 

            

 

 

Step 6: test execution and output results

         

 

Tool class: PagePlugin java,Page.java, PageHelper.java, where PagePlugin is a plug-in for MyBatis paging.

        PagePlugin:

         

@Intercepts( { @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
	public class PagePlugin implements Interceptor {

		private static String dialect = "";
		private static String pageSqlId = "";

		@SuppressWarnings("unchecked")
		public Object intercept(Invocation ivk) throws Throwable {

			if (ivk.getTarget() instanceof RoutingStatementHandler) {
				RoutingStatementHandler statementHandler = (RoutingStatementHandler) ivk
						.getTarget();
				BaseStatementHandler delegate = (BaseStatementHandler) ReflectHelper
						.getValueByFieldName(statementHandler, "delegate");
				MappedStatement mappedStatement = (MappedStatement) ReflectHelper
						.getValueByFieldName(delegate, "mappedStatement");

				if (mappedStatement.getId().matches(pageSqlId)) {
					BoundSql boundSql = delegate.getBoundSql();
					Object parameterObject = boundSql.getParameterObject();
					if (parameterObject == null) {
						throw new NullYiibaierException("parameterObject error");
					} else {
						Connection connection = (Connection) ivk.getArgs()[0];
						String sql = boundSql.getSql();
						String countSql = "select count(0) from (" + sql
								+ ") myCount";
						System.out.println("total sql sentence:" + countSql);
						PreparedStatement countStmt = connection
								.prepareStatement(countSql);
						BoundSql countBS = new BoundSql(mappedStatement
								.getConfiguration(), countSql, boundSql
								.getParameterMappings(), parameterObject);
						setParameters(countStmt, mappedStatement, countBS,
								parameterObject);
						ResultSet rs = countStmt.executeQuery();
						int count = 0;
						if (rs.next()) {
							count = rs.getInt(1);
						}
						rs.close();
						countStmt.close();

						Page page = null;
						if (parameterObject instanceof Page) {
							page = (Page) parameterObject;
							page.setTotalResult(count);
						} else if (parameterObject instanceof Map) {
							Map<String, Object> map = (Map<String, Object>) parameterObject;
							page = (Page) map.get("page");
							if (page == null)
								page = new Page();
							page.setTotalResult(count);
						} else {
							Field pageField = ReflectHelper.getFieldByFieldName(
									parameterObject, "page");
							if (pageField != null) {
								page = (Page) ReflectHelper.getValueByFieldName(
										parameterObject, "page");
								if (page == null)
									page = new Page();
								page.setTotalResult(count);
								ReflectHelper.setValueByFieldName(parameterObject,
										"page", page);
							} else {
								throw new NoSuchFieldException(parameterObject
										.getClass().getName());
							}
						}
						String pageSql = generatePageSql(sql, page);
						System.out.println("page sql:" + pageSql);
						ReflectHelper.setValueByFieldName(boundSql, "sql", pageSql);
					}
				}
			}
			return ivk.proceed();
		}

		private void setParameters(PreparedStatement ps,
				MappedStatement mappedStatement, BoundSql boundSql,
				Object parameterObject) throws SQLException {
			ErrorContext.instance().activity("setting parameters").object(
					mappedStatement.getParameterMap().getId());
			List<ParameterMapping> parameterMappings = boundSql
					.getParameterMappings();
			if (parameterMappings != null) {
				Configuration configuration = mappedStatement.getConfiguration();
				TypeHandlerRegistry typeHandlerRegistry = configuration
						.getTypeHandlerRegistry();
				MetaObject metaObject = parameterObject == null ? null
						: configuration.newMetaObject(parameterObject);
				for (int i = 0; i < parameterMappings.size(); i++) {
					ParameterMapping parameterMapping = parameterMappings.get(i);
					if (parameterMapping.getMode() != ParameterMode.OUT) {
						Object value;
						String propertyName = parameterMapping.getProperty();
						PropertyTokenizer prop = new PropertyTokenizer(propertyName);
						if (parameterObject == null) {
							value = null;
						} else if (typeHandlerRegistry
								.hasTypeHandler(parameterObject.getClass())) {
							value = parameterObject;
						} else if (boundSql.hasAdditionalParameter(propertyName)) {
							value = boundSql.getAdditionalParameter(propertyName);
						} else if (propertyName
								.startsWith(ForEachSqlNode.ITEM_PREFIX)
								&& boundSql.hasAdditionalParameter(prop.getName())) {
							value = boundSql.getAdditionalParameter(prop.getName());
							if (value != null) {
								value = configuration.newMetaObject(value)
										.getValue(
												propertyName.substring(prop
														.getName().length()));
							}
						} else {
							value = metaObject == null ? null : metaObject
									.getValue(propertyName);
						}
						TypeHandler typeHandler = parameterMapping.getTypeHandler();
						if (typeHandler == null) {
							throw new ExecutorException(
									"There was no TypeHandler found for parameter "
											+ propertyName + " of statement "
											+ mappedStatement.getId());
						}
						typeHandler.setParameter(ps, i + 1, value, parameterMapping
								.getJdbcType());
					}
				}
			}
		}

		private String generatePageSql(String sql, Page page) {
			if (page != null && (dialect != null || !dialect.equals(""))) {
				StringBuffer pageSql = new StringBuffer();
				if ("mysql".equals(dialect)) {
					pageSql.append(sql);
					pageSql.append(" limit " + page.getCurrentResult() + ","
							+ page.getShowCount());
				} else if ("oracle".equals(dialect)) {
					pageSql
							.append("select * from (select tmp_tb.*,ROWNUM row_id from (");
					pageSql.append(sql);
					pageSql.append(")  tmp_tb where ROWNUM<=");
					pageSql.append(page.getCurrentResult() + page.getShowCount());
					pageSql.append(") where row_id>");
					pageSql.append(page.getCurrentResult());
				}
				return pageSql.toString();
			} else {
				return sql;
			}
		}

		public Object plugin(Object arg0) {
			// TODO Auto-generated method stub
			return Plugin.wrap(arg0, this);
		}

		public void setProperties(Properties p) {
			dialect = p.getProperty("dialect");
			if (dialect == null || dialect.equals("")) {
				try {
					throw new PropertyException("dialect property is not found!");
				} catch (PropertyException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			pageSqlId = p.getProperty("pageSqlId");
			if (dialect == null || dialect.equals("")) {
				try {
					throw new PropertyException("pageSqlId property is not found!");
				} catch (PropertyException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}

	}

Results:

     

 

 

Learning source: https://www.yiibai.com/mybatis/mybatis_pagination.html#article-start

Tags: Mybatis

Posted by PugJr on Mon, 16 May 2022 16:49:17 +0300