com.badminton.interceptors.mySqlHelper.pagehelper.util.SqlUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.badminton.interceptors.mySqlHelper.pagehelper.util.SqlUtil.java

Source

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 abel533@gmail.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.badminton.interceptors.mySqlHelper.pagehelper.util;

import com.badminton.interceptors.mySqlHelper.pagehelper.Constant;
import com.badminton.interceptors.mySqlHelper.pagehelper.Dialect;
import com.badminton.interceptors.mySqlHelper.pagehelper.dialect.AbstractDialect;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Mybatis - sql?countMappedStatement?
 *
 * @author liuzh/abel533/isea533
 * @since 3.6.0
 * ? : http://git.oschina.net/free/Mybatis_PageHelper
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public class SqlUtil extends BaseSqlUtil implements Constant {
    private Dialect dialect;
    private Field additionalParametersField;
    private Properties properties;

    //?dialect,setPropertiessetSqlUtilConfig?
    protected boolean autoDialect = true;
    //??dialect
    protected boolean autoRuntimeDialect;
    //???jdbcurl????
    protected boolean closeConn = true;
    //
    private Map<String, Dialect> urlDialectMap = new ConcurrentHashMap<String, Dialect>();
    private ReentrantLock lock = new ReentrantLock();

    /**
     * 
     *
     * @param invocation
     * @return
     * @throws Throwable
     */
    public Object intercept(Invocation invocation) throws Throwable {
        try {
            return doIntercept(invocation);
        } finally {
            clearLocalPage();
        }
    }

    /**
     * 
     *
     * @param invocation
     * @return
     * @throws Throwable
     */
    public Object doIntercept(Invocation invocation) throws Throwable {
        //??
        Object[] args = invocation.getArgs();
        MappedStatement ms = (MappedStatement) args[0];
        Object parameterObject = args[1];
        RowBounds rowBounds = (RowBounds) args[2];
        List resultList;
        if (autoDialect) {
            lock.lock();
            try {
                if (autoDialect) {
                    autoDialect = false;
                    this.dialect = getDialect(ms);
                }
            } finally {
                lock.unlock();
            }
        }
        Dialect runtimeDialect = dialect;
        if (autoRuntimeDialect) {
            runtimeDialect = getDialect(ms);
        }
        //????
        if (!runtimeDialect.skip(ms, parameterObject, rowBounds)) {
            ResultHandler resultHandler = (ResultHandler) args[3];
            //?
            Executor executor = (Executor) invocation.getTarget();
            BoundSql boundSql = ms.getBoundSql(parameterObject);
            //?????
            Map<String, Object> additionalParameters = (Map<String, Object>) additionalParametersField
                    .get(boundSql);
            //?? count 
            if (runtimeDialect.beforeCount(ms, parameterObject, rowBounds)) {
                // count  key
                CacheKey countKey = executor.createCacheKey(ms, parameterObject, RowBounds.DEFAULT, boundSql);
                countKey.update("_Count");
                MappedStatement countMs = msCountMap.get(countKey);
                if (countMs == null) {
                    //?? ms  Long  ms
                    countMs = MSUtils.newCountMappedStatement(ms);
                    msCountMap.put(countKey, countMs);
                }
                //? count sql
                String countSql = runtimeDialect.getCountSql(ms, boundSql, parameterObject, rowBounds, countKey);
                BoundSql countBoundSql = new BoundSql(ms.getConfiguration(), countSql,
                        boundSql.getParameterMappings(), parameterObject);
                //? SQL ???? BoundSql 
                for (String key : additionalParameters.keySet()) {
                    countBoundSql.setAdditionalParameter(key, additionalParameters.get(key));
                }
                // count 
                Object countResultList = executor.query(countMs, parameterObject, RowBounds.DEFAULT, resultHandler,
                        countKey, countBoundSql);
                Long count = (Long) ((List) countResultList).get(0);
                //?
                runtimeDialect.afterCount(count, parameterObject, rowBounds);
                if (count == 0L) {
                    // 0 
                    return runtimeDialect.afterPage(new ArrayList(), parameterObject, rowBounds);
                }
            }
            //??
            if (runtimeDialect.beforePage(ms, parameterObject, rowBounds)) {
                //? key
                CacheKey pageKey = executor.createCacheKey(ms, parameterObject, rowBounds, boundSql);
                //??
                parameterObject = runtimeDialect.processParameterObject(ms, parameterObject, boundSql, pageKey);
                //? sql
                String pageSql = runtimeDialect.getPageSql(ms, boundSql, parameterObject, rowBounds, pageKey);
                BoundSql pageBoundSql = new BoundSql(ms.getConfiguration(), pageSql,
                        boundSql.getParameterMappings(), parameterObject);
                //??
                for (String key : additionalParameters.keySet()) {
                    pageBoundSql.setAdditionalParameter(key, additionalParameters.get(key));
                }
                //
                resultList = executor.query(ms, parameterObject, RowBounds.DEFAULT, resultHandler, pageKey,
                        pageBoundSql);
            } else {
                resultList = new ArrayList();
            }
        } else {
            args[2] = RowBounds.DEFAULT;
            resultList = (List) invocation.proceed();
        }
        //
        return runtimeDialect.afterPage(resultList, parameterObject, rowBounds);
    }

    /**
     * ? dialect
     *
     * @param dialectClass
     * @param properties
     */
    private Dialect initDialect(String dialectClass, Properties properties) {
        Dialect dialect;
        if (StringUtil.isEmpty(dialectClass)) {
            throw new RuntimeException(" PageHelper ? dialect ");
        }
        try {
            Class sqlDialectClass = resloveDialectClass(dialectClass);
            if (AbstractDialect.class.isAssignableFrom(sqlDialectClass)) {
                dialect = (Dialect) sqlDialectClass.getConstructor(SqlUtil.class).newInstance(this);
            } else {
                dialect = (Dialect) sqlDialectClass.newInstance();
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("? dialect [" + dialectClass + "]:" + e.getMessage());
        }
        dialect.setProperties(properties);
        return dialect;
    }

    /**
     * ?url
     *
     * @param dataSource
     * @return
     */
    public String getUrl(DataSource dataSource) {
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            return conn.getMetaData().getURL();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            if (conn != null) {
                try {
                    if (closeConn) {
                        conn.close();
                    }
                } catch (SQLException e) {
                    //ignore
                }
            }
        }
    }

    /**
     * ?datasourcesqlUtil
     *
     * @param ms
     */
    public Dialect getDialect(MappedStatement ms) {
        //dataSource?
        DataSource dataSource = ms.getConfiguration().getEnvironment().getDataSource();
        String url = getUrl(dataSource);
        if (urlDialectMap.containsKey(url)) {
            return urlDialectMap.get(url);
        }
        try {
            lock.lock();
            if (urlDialectMap.containsKey(url)) {
                return urlDialectMap.get(url);
            }
            if (StringUtil.isEmpty(url)) {
                throw new RuntimeException("?jdbcUrl??dialect?!");
            }
            String dialectStr = fromJdbcUrl(url);
            if (dialectStr == null) {
                throw new RuntimeException("?? dialect ?!");
            }
            Dialect dialect = initDialect(dialectStr, properties);
            urlDialectMap.put(url, dialect);
            return dialect;
        } finally {
            lock.unlock();
        }
    }

    public void setProperties(Properties properties) {
        super.setProperties(properties);
        //???jdbcurl????
        String closeConn = properties.getProperty("closeConn");
        //#97
        if (StringUtil.isNotEmpty(closeConn)) {
            this.closeConn = Boolean.parseBoolean(closeConn);
        }
        //?
        String dialect = properties.getProperty("dialect");
        String runtimeDialect = properties.getProperty("autoRuntimeDialect");
        if (StringUtil.isNotEmpty(runtimeDialect) && runtimeDialect.equalsIgnoreCase("TRUE")) {
            this.autoRuntimeDialect = true;
            this.autoDialect = false;
            this.properties = properties;
        } else if (StringUtil.isEmpty(dialect)) {
            autoDialect = true;
            this.properties = properties;
        } else {
            autoDialect = false;
            this.dialect = initDialect(dialect, properties);
        }
        try {
            //??? BoundSql  additionalParameters 
            additionalParametersField = BoundSql.class.getDeclaredField("additionalParameters");
            additionalParametersField.setAccessible(true);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
    }
}