com.bsb.cms.commons.page.interceptor.PaginationInterceptor.java Source code

Java tutorial

Introduction

Here is the source code for com.bsb.cms.commons.page.interceptor.PaginationInterceptor.java

Source

/**
 * @(#)${file_name} ${date}
 *
 * Copyright (c) 2014-2015 BuShangBan (China) Int'l Co., Ltd
 * yongtai Road. pu dong District.Shanghai China
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of BuShangBan (China)
 *  Int'l Co., Ltd ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with BuShangBan (China).
 */
package com.bsb.cms.commons.page.interceptor;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.SqlSource;
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.scripting.defaults.DefaultParameterHandler;
import org.apache.ibatis.session.RowBounds;

import com.bsb.cms.commons.page.PageContext;
import com.bsb.cms.commons.page.Pagination;

/**
 * mybatis?
 * 
 * @author hongjian.liu
 * @version 1.0.0 2014-6-4
 * @since 1.0
 */
@Intercepts({
        @org.apache.ibatis.plugin.Signature(type = org.apache.ibatis.executor.Executor.class, method = "query", args = {
                MappedStatement.class, Object.class, RowBounds.class,
                org.apache.ibatis.session.ResultHandler.class }) })
public class PaginationInterceptor implements Interceptor {
    // log
    private static final Log log = LogFactory.getLog(PaginationInterceptor.class);
    // private static String dialect = ""; // ?
    private static String pageSqlId = ".*ListPage$"; // mapper.xml?ID(?)

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.ibatis.plugin.Interceptor#intercept(org.apache.ibatis.plugin
     * .Invocation)
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // ? MappedStatementBoundSql?sql?
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];

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

            Object parameter = invocation.getArgs()[1];
            BoundSql boundSql = mappedStatement.getBoundSql(parameter);
            String originalSql = boundSql.getSql().trim();
            Object parameterObject = boundSql.getParameterObject();

            /*
             * if (parameterObject != null) { page =
             * (Page)ReflectHelper.isPage(parameterObject, "page"); }
             * 
             * if ((page == null) && (context.isPagination())) { page = context;
             * }
             */
            // Pagination page = null;
            PageContext page = PageContext.getContext();
            // Page??
            String countSql = getCountSql(originalSql);
            Connection connection = mappedStatement.getConfiguration().getEnvironment().getDataSource()
                    .getConnection();
            PreparedStatement countStmt = connection.prepareStatement(countSql);
            BoundSql countBS = copyFromBoundSql(mappedStatement, boundSql, countSql);
            log.debug("countSql=" + countSql);
            DefaultParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject,
                    countBS);
            parameterHandler.setParameters(countStmt);
            ResultSet rs = countStmt.executeQuery();
            int totpage = 0;
            if (rs.next()) {
                totpage = rs.getInt(1);
            }
            rs.close();
            countStmt.close();
            connection.close();// TODO

            // 
            page.init(totpage, page.getPageSize(), page.getCurrentPage());

            if ((StringUtils.isNotEmpty(page.getOrderBy())) && (originalSql.indexOf("BUSINESS_CIRCLE") == -1)) {
                originalSql = originalSql + " ORDER BY " + page.getOrderBy();
            }

            String pageSql = buildPageSqlForMysql(originalSql, page).toString();
            BoundSql newBoundSql = copyFromBoundSql(mappedStatement, boundSql, pageSql);
            MappedStatement newMs = copyFromMappedStatement(mappedStatement, new BoundSqlSqlSource(newBoundSql));
            log.debug("newMs=" + pageSql);
            invocation.getArgs()[0] = newMs;
        }

        return invocation.proceed();
    }

    /**
     * ?MappedStatement
     */
    private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource) {
        MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms.getId(),
                newSqlSource, ms.getSqlCommandType());
        builder.resource(ms.getResource());
        builder.fetchSize(ms.getFetchSize());
        builder.statementType(ms.getStatementType());
        builder.keyGenerator(ms.getKeyGenerator());
        String[] keyProperties = ms.getKeyProperties();
        String keyProperty = "";
        if ((keyProperties != null) && (keyProperties.length > 0))
            for (String kp : keyProperties)
                keyProperty = keyProperty + "," + kp;

        if (StringUtils.isNotEmpty(keyProperty))
            keyProperty = keyProperty.substring(1);
        builder.keyProperty(keyProperty);
        builder.timeout(ms.getTimeout());
        builder.parameterMap(ms.getParameterMap());
        builder.resultMaps(ms.getResultMaps());
        builder.cache(ms.getCache());
        MappedStatement newMs = builder.build();
        return newMs;
    }

    /**
     * ?BoundSql
     */
    private BoundSql copyFromBoundSql(MappedStatement ms, BoundSql boundSql, String sql) {
        BoundSql newBoundSql = new BoundSql(ms.getConfiguration(), sql, boundSql.getParameterMappings(),
                boundSql.getParameterObject());
        for (ParameterMapping mapping : boundSql.getParameterMappings()) {
            String prop = mapping.getProperty();
            if (boundSql.hasAdditionalParameter(prop)) {
                newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));
            }
        }
        return newBoundSql;
    }

    /**
     * Sqllimit mysql
     * 
     * @param sql
     * @param page
     * @return
     */
    public StringBuilder buildPageSqlForMysql(String sql, Pagination page) {
        StringBuilder pageSql = new StringBuilder(100);
        String beginrow = String.valueOf((page.getCurrentPage() - 1) * page.getPageSize());
        pageSql.append(sql);
        pageSql.append(" limit " + beginrow + "," + page.getPageSize());
        return pageSql;
    }

    /**
     * ?Sql??Sql?
     */
    private String getCountSql(String sql) {
        return "SELECT COUNT(*) FROM (" + sql + ") aliasForPage";
    }

    public class BoundSqlSqlSource implements SqlSource {
        BoundSql boundSql;

        public BoundSqlSqlSource(BoundSql boundSql) {
            this.boundSql = boundSql;
        }

        public BoundSql getBoundSql(Object parameterObject) {
            return boundSql;
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.ibatis.plugin.Interceptor#plugin(java.lang.Object)
     */
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.ibatis.plugin.Interceptor#setProperties(java.util.Properties)
     */
    @Override
    public void setProperties(Properties properties) {

    }

}