Java tutorial
/* * 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); } } }