/* * Copyright (c) 2019 TOYOTA MOTOR CORPORATION * * 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 app.market.persistence.interceptor; import java.sql.Connection; import java.util.Properties; import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.reflect.FieldUtils; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.BoundSql; 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.session.RowBounds; @Intercepts(@Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class })) public class PaginationInterceptor implements Interceptor { private final static String SQL_SELECT_REGEX = "(?is)^\\s*SELECT.*$"; private final static String SQL_COUNT_REGEX = "(?is)^\\s*SELECT\\s+COUNT\\s*\\(\\s*(?:\\*|\\w+)\\s*\\).*$"; @Override public Object intercept(Invocation inv) throws Throwable { StatementHandler target = (StatementHandler) inv.getTarget(); BoundSql boundSql = target.getBoundSql(); String sql = boundSql.getSql(); if ( StringUtils.isBlank( sql ) ) { return inv.proceed(); } if ( sql.matches( SQL_SELECT_REGEX ) && !Pattern.matches( SQL_COUNT_REGEX, sql ) ) { Object obj = FieldUtils.readField( target, "delegate", true ); RowBounds rowBounds = (RowBounds) FieldUtils.readField( obj, "rowBounds", true ); if ( rowBounds != null && rowBounds != RowBounds.DEFAULT ) { FieldUtils.writeField( boundSql, "sql", newSql( sql, rowBounds ), true ); FieldUtils.writeField( rowBounds, "offset", RowBounds.NO_ROW_OFFSET, true ); FieldUtils.writeField( rowBounds, "limit", RowBounds.NO_ROW_LIMIT, true ); } } return inv.proceed(); } public String newSql(String oldSql, RowBounds rowBounds) { String end = " limit " + rowBounds.getOffset() + "," + rowBounds.getLimit(); return oldSql + end; } @Override public Object plugin(Object target) { return Plugin.wrap( target, this ); } @Override public void setProperties(Properties arg0) { } }