All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor Maven / Gradle / Ivy

There is a newer version: 3.5.7
Show newest version
/*
 * Copyright (c) 2011-2020, hubin ([email protected]).
 * 

* Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at *

* http://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.baomidou.mybatisplus.extension.plugins; import static java.util.stream.Collectors.joining; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Arrays; import java.util.Map; import java.util.Properties; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlCommandType; 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 org.apache.ibatis.scripting.defaults.DefaultParameterHandler; import org.apache.ibatis.session.RowBounds; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.core.MybatisDefaultParameterHandler; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.parser.ISqlParser; import com.baomidou.mybatisplus.core.parser.SqlInfo; import com.baomidou.mybatisplus.core.toolkit.ArrayUtils; import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils; import com.baomidou.mybatisplus.core.toolkit.PluginUtils; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.extension.handlers.AbstractSqlParserHandler; import com.baomidou.mybatisplus.extension.plugins.pagination.DialectFactory; import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils; import com.baomidou.mybatisplus.extension.toolkit.SqlParserUtils; import lombok.Setter; import lombok.experimental.Accessors; /** *

* 分页拦截器 *

* * @author hubin * @since 2016-01-23 */ @Setter @Accessors(chain = true) @Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})}) public class PaginationInterceptor extends AbstractSqlParserHandler implements Interceptor { /** * COUNT SQL 解析 */ private ISqlParser sqlParser; /** * 溢出总页数,设置第一页 */ private boolean overflow = false; /** * 方言类型 */ private String dialectType; /** * 方言实现类 */ private String dialectClazz; /** * 查询SQL拼接Order By * * @param originalSql 需要拼接的SQL * @param page page对象 * @param orderBy 是否需要拼接Order By * @return */ public static String concatOrderBy(String originalSql, IPage page, boolean orderBy) { if (orderBy && (ArrayUtils.isNotEmpty(page.ascs()) || ArrayUtils.isNotEmpty(page.descs()))) { StringBuilder buildSql = new StringBuilder(originalSql); String ascStr = concatOrderBuilder(page.ascs(), " ASC"); String descStr = concatOrderBuilder(page.descs(), " DESC"); if (StringUtils.isNotEmpty(ascStr) && StringUtils.isNotEmpty(descStr)) { ascStr += ", "; } if (StringUtils.isNotEmpty(ascStr) || StringUtils.isNotEmpty(descStr)) { buildSql.append(" ORDER BY ").append(ascStr).append(descStr); } return buildSql.toString(); } return originalSql; } /** * 拼接多个排序方法 * * @param columns * @param orderWord */ private static String concatOrderBuilder(String[] columns, String orderWord) { if (ArrayUtils.isNotEmpty(columns)) { return Arrays.stream(columns).filter(StringUtils::isNotEmpty) .collect(joining(StringPool.COMMA, StringPool.EMPTY, orderWord)); } return StringUtils.EMPTY; } /** * Physical Page Interceptor for all the queries with parameter {@link RowBounds} */ @Override public Object intercept(Invocation invocation) throws Throwable { StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget()); MetaObject metaObject = SystemMetaObject.forObject(statementHandler); // SQL 解析 this.sqlParser(metaObject); // 先判断是不是SELECT操作 MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement"); if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) { return invocation.proceed(); } // 针对定义了rowBounds,做为mapper接口方法的参数 BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql"); Object paramObj = boundSql.getParameterObject(); // 判断参数里是否有page对象 IPage page = null; if (paramObj instanceof IPage) { page = (IPage) paramObj; } else if (paramObj instanceof Map) { for (Object arg : ((Map) paramObj).values()) { if (arg instanceof IPage) { page = (IPage) arg; break; } } } /** * 不需要分页的场合,如果 size 小于 0 返回结果集 */ if (null == page || page.getSize() < 0) { return invocation.proceed(); } String originalSql = boundSql.getSql(); Connection connection = (Connection) invocation.getArgs()[0]; DbType dbType = StringUtils.isNotEmpty(dialectType) ? DbType.getDbType(dialectType) : JdbcUtils.getDbType(connection.getMetaData().getURL()); boolean orderBy = true; if (page.getTotal() == 0) { SqlInfo sqlInfo = SqlParserUtils.getOptimizeCountSql(page.optimizeCountSql(), sqlParser, originalSql); orderBy = sqlInfo.isOrderBy(); this.queryTotal(overflow, sqlInfo.getSql(), mappedStatement, boundSql, page, connection); if (page.getTotal() <= 0) { return invocation.proceed(); } } String buildSql = concatOrderBy(originalSql, page, orderBy); originalSql = DialectFactory.buildPaginationSql(page, buildSql, dbType, dialectClazz); /* *

禁用内存分页

*

内存分页会查询所有结果出来处理(这个很吓人的),如果结果变化频繁这个数据还会不准。

*/ metaObject.setValue("delegate.boundSql.sql", originalSql); metaObject.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET); metaObject.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT); return invocation.proceed(); } /** * 查询总记录条数 * * @param sql * @param mappedStatement * @param boundSql * @param page */ protected void queryTotal(boolean overflowCurrent, String sql, MappedStatement mappedStatement, BoundSql boundSql, IPage page, Connection connection) { try (PreparedStatement statement = connection.prepareStatement(sql)) { DefaultParameterHandler parameterHandler = new MybatisDefaultParameterHandler(mappedStatement, boundSql.getParameterObject(), boundSql); parameterHandler.setParameters(statement); long total = 0; try (ResultSet resultSet = statement.executeQuery()) { if (resultSet.next()) { total = resultSet.getLong(1); } } page.setTotal(total); /* * 溢出总页数,设置第一页 */ long pages = page.getPages(); if (overflowCurrent && page.getCurrent() > pages) { // 设置为第一条 page.setCurrent(1); } } catch (Exception e) { throw ExceptionUtils.mpe("Error: Method queryTotal execution error.", e); } } @Override public Object plugin(Object target) { if (target instanceof StatementHandler) { return Plugin.wrap(target, this); } return target; } @Override public void setProperties(Properties prop) { String dialectType = prop.getProperty("dialectType"); String dialectClazz = prop.getProperty("dialectClazz"); if (StringUtils.isNotEmpty(dialectType)) { this.dialectType = dialectType; } if (StringUtils.isNotEmpty(dialectClazz)) { this.dialectClazz = dialectClazz; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy