com.beginner.core.page.PagePlugin.java Source code

Java tutorial

Introduction

Here is the source code for com.beginner.core.page.PagePlugin.java

Source

/*
 * Copyright 2015-9999 the original author or authors.
 *
 * 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.beginner.core.page;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;

import javax.xml.bind.PropertyException;

import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.ExecutorException;
import org.apache.ibatis.executor.statement.BaseStatementHandler;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
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.property.PropertyTokenizer;
import org.apache.ibatis.scripting.xmltags.ForEachSqlNode;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;

import com.beginner.core.utils.ReflectHelper;
import com.beginner.core.utils.Tools;

/**
* <b>??</b>PagePlugin<br/>
* <b>??</b>?<br/>
* <b></b>Hsiao Lin Studio<br/>
* <b></b><br/>
* <b></b>20150521 ?6:18:18<br/>
* <b></b><br/>
* @version 1.0.0<br/>
*/
@SuppressWarnings(value = { "unchecked", "rawtypes" })
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class PagePlugin implements Interceptor {

    /**
     * ?
     */
    private static String databaseDialect = "";

    /**
     * XXXMapper.xml?SQLID(?)
     */
    private static String mappedStatementId = "";

    /**
     * ?
     */
    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");

            //?SQL
            if (mappedStatement.getId().matches(mappedStatementId)) {

                BoundSql boundSql = delegate.getBoundSql();
                //SQL<select>parameterType??Mapper??,??
                Object parameterObject = boundSql.getParameterObject();

                if (parameterObject == null) {
                    throw new NullPointerException("parameterObject?");
                } else {
                    Connection connection = (Connection) ivk.getArgs()[0];
                    String sql = boundSql.getSql();

                    //
                    String countSql = "SELECT COUNT(0) FROM (" + sql + ") tmp_count";
                    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 = (Page) parameterObject;
                        page.setEntityOrField(true);
                        page.setTotalResult(count);
                    } else { //??Page
                        Field pageField = ReflectHelper.getFieldByFieldName(parameterObject, "page");
                        if (pageField != null) {
                            page = (Page) ReflectHelper.getValueByFieldName(parameterObject, "page");
                            if (page == null)
                                page = new Page();
                            page.setEntityOrField(false);
                            page.setTotalResult(count);
                            //??
                            ReflectHelper.setValueByFieldName(parameterObject, "page", page);
                        } else {
                            throw new NoSuchFieldException(
                                    parameterObject.getClass().getName() + "? page ?");
                        }
                    }
                    String pageSql = generatePageSql(sql, page);
                    //sql???BoundSql.
                    ReflectHelper.setValueByFieldName(boundSql, "sql", pageSql);
                }
            }
        }
        return ivk.proceed();
    }

    /**
     * SQL?(?)
     * ?org.apache.ibatis.executor.parameter.DefaultParameterHandler
     */
    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());
                }
            }
        }
    }

    /**
     * ???sql
     */
    private String generatePageSql(String sql, Page page) {
        if (page != null && Tools.isNotEmpty(databaseDialect)) {
            StringBuffer pageSql = new StringBuffer();
            if ("mysql".equals(databaseDialect)) {
                pageSql.append(sql);
                pageSql.append(" LIMIT " + page.getCurrentResult() + "," + page.getShowCount());
            } else if ("oracle".equals(databaseDialect)) {
                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;
        }
    }

    /**
     * ??ID??
     */
    public void setProperties(Properties p) {
        databaseDialect = p.getProperty("databaseDialect");
        if (Tools.isEmpty(databaseDialect)) {
            try {
                throw new PropertyException("databaseDialect property is not found!");
            } catch (PropertyException e) {
                e.printStackTrace();
            }
        }
        mappedStatementId = p.getProperty("mappedStatementId");
        if (Tools.isEmpty(mappedStatementId)) {
            try {
                throw new PropertyException("mappedStatementId property is not found!");
            } catch (PropertyException e) {
                e.printStackTrace();
            }
        }
    }

    public Object plugin(Object arg0) {
        return Plugin.wrap(arg0, this);
    }
}