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.swifts.frame.common.pagehelper; import com.swifts.frame.common.pagehelper.*; import com.swifts.frame.common.pagehelper.MSUtils; import com.swifts.frame.common.pagehelper.Page; import com.swifts.frame.common.pagehelper.parser.Parser; import com.swifts.frame.common.pagehelper.parser.impl.AbstractParser; import com.swifts.frame.common.pagehelper.sqlsource.*; import org.apache.ibatis.builder.StaticSqlSource; import org.apache.ibatis.builder.annotation.ProviderSqlSource; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlSource; import org.apache.ibatis.plugin.Invocation; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.SystemMetaObject; import org.apache.ibatis.scripting.defaults.RawSqlSource; import org.apache.ibatis.scripting.xmltags.DynamicSqlSource; import org.apache.ibatis.session.RowBounds; import java.lang.reflect.Method; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; /** * Mybatis - sql?countMappedStatement? * * @author liuzh/abel533/isea533 * @since 3.6.0 * ? : http://git.oschina.net/free/Mybatis_PageHelper */ @SuppressWarnings({ "rawtypes", "unchecked" }) public class SqlUtil implements Constant { private static final ThreadLocal<com.swifts.frame.common.pagehelper.Page> LOCAL_PAGE = new ThreadLocal<com.swifts.frame.common.pagehelper.Page>(); //params? private static Map<String, String> PARAMS = new HashMap<String, String>(5); //request? private static Boolean hasRequest; private static Class<?> requestClass; private static Method getParameterMap; static { try { requestClass = Class.forName("javax.servlet.ServletRequest"); getParameterMap = requestClass.getMethod("getParameterMap", new Class[] {}); hasRequest = true; } catch (Exception e) { hasRequest = false; } } //countms private static final Map<String, MappedStatement> msCountMap = new ConcurrentHashMap<String, MappedStatement>(); //RowBounds?offsetPageNum - ? private boolean offsetAsPageNum = false; //RowBounds?count - ? private boolean rowBoundsWithCount = false; //truepagesize0RowBoundslimit=0? private boolean pageSizeZero = false; //?? private boolean reasonable = false; //?parser private Parser parser; //??????false private boolean supportMethodsArguments = false; /** * * * @param strDialect */ public SqlUtil(String strDialect) { if (strDialect == null || "".equals(strDialect)) { throw new IllegalArgumentException("Mybatis??dialect?!"); } Exception exception = null; try { com.swifts.frame.common.pagehelper.Dialect dialect = com.swifts.frame.common.pagehelper.Dialect .of(strDialect); parser = AbstractParser.newParser(dialect); } catch (Exception e) { exception = e; //????? try { Class<?> parserClass = Class.forName(strDialect); if (Parser.class.isAssignableFrom(parserClass)) { parser = (Parser) parserClass.newInstance(); } } catch (ClassNotFoundException ex) { exception = ex; } catch (InstantiationException ex) { exception = ex; } catch (IllegalAccessException ex) { exception = ex; } } if (parser == null) { throw new RuntimeException(exception); } } public static Boolean getCOUNT() { com.swifts.frame.common.pagehelper.Page page = getLocalPage(); if (page != null) { return page.getCountSignal(); } return null; } /** * ?Page? * * @return */ public static <T> com.swifts.frame.common.pagehelper.Page<T> getLocalPage() { return LOCAL_PAGE.get(); } public static void setLocalPage(com.swifts.frame.common.pagehelper.Page page) { LOCAL_PAGE.set(page); } /** * ?? */ public static void clearLocalPage() { LOCAL_PAGE.remove(); } /** * ?? * * @param params * @return */ public static <T> com.swifts.frame.common.pagehelper.Page<T> getPageFromObject(Object params) { int pageNum; int pageSize; MetaObject paramsObject = null; if (params == null) { throw new NullPointerException("??!"); } if (hasRequest && requestClass.isAssignableFrom(params.getClass())) { try { paramsObject = SystemMetaObject.forObject(getParameterMap.invoke(params, new Object[] {})); } catch (Exception e) { // } } else { paramsObject = SystemMetaObject.forObject(params); } if (paramsObject == null) { throw new NullPointerException("??!"); } Object orderBy = getParamValue(paramsObject, "orderBy", false); boolean hasOrderBy = false; if (orderBy != null && orderBy.toString().length() > 0) { hasOrderBy = true; } try { Object _pageNum = getParamValue(paramsObject, "pageNum", hasOrderBy ? false : true); Object _pageSize = getParamValue(paramsObject, "pageSize", hasOrderBy ? false : true); if (_pageNum == null || _pageSize == null) { com.swifts.frame.common.pagehelper.Page page = new com.swifts.frame.common.pagehelper.Page(); page.setOrderBy(orderBy.toString()); page.setOrderByOnly(true); return page; } pageNum = Integer.parseInt(String.valueOf(_pageNum)); pageSize = Integer.parseInt(String.valueOf(_pageSize)); } catch (NumberFormatException e) { throw new IllegalArgumentException("???!"); } com.swifts.frame.common.pagehelper.Page page = new com.swifts.frame.common.pagehelper.Page(pageNum, pageSize); //count Object _count = getParamValue(paramsObject, "count", false); if (_count != null) { page.setCount(Boolean.valueOf(String.valueOf(_count))); } //? if (hasOrderBy) { page.setOrderBy(orderBy.toString()); } //?? Object reasonable = getParamValue(paramsObject, "reasonable", false); if (reasonable != null) { page.setReasonable(Boolean.valueOf(String.valueOf(reasonable))); } // Object pageSizeZero = getParamValue(paramsObject, "pageSizeZero", false); if (pageSizeZero != null) { page.setPageSizeZero(Boolean.valueOf(String.valueOf(pageSizeZero))); } return page; } /** * ?? * * @param paramsObject * @param paramName * @param required * @return */ public static Object getParamValue(MetaObject paramsObject, String paramName, boolean required) { Object value = null; if (paramsObject.hasGetter(PARAMS.get(paramName))) { value = paramsObject.getValue(PARAMS.get(paramName)); } if (value != null && value.getClass().isArray()) { Object[] values = (Object[]) value; if (values.length == 0) { value = null; } else { value = values[0]; } } if (required && value == null) { throw new RuntimeException("??:" + PARAMS.get(paramName)); } return value; } /** * ??? * * @param ms * @return */ public boolean isPageSqlSource(MappedStatement ms) { if (ms.getSqlSource() instanceof PageSqlSource) { return true; } return false; } /** * [?]countsql * * @param dialect ? * @param originalSql sql * @deprecated 5.x */ @Deprecated public static void testSql(String dialect, String originalSql) { testSql(com.swifts.frame.common.pagehelper.Dialect.of(dialect), originalSql); } /** * [?]countsql * * @param dialect ? * @param originalSql sql * @deprecated 5.x */ @Deprecated public static void testSql(com.swifts.frame.common.pagehelper.Dialect dialect, String originalSql) { Parser parser = AbstractParser.newParser(dialect); if (dialect == com.swifts.frame.common.pagehelper.Dialect.sqlserver) { setLocalPage(new com.swifts.frame.common.pagehelper.Page(1, 10)); } String countSql = parser.getCountSql(originalSql); System.out.println(countSql); String pageSql = parser.getPageSql(originalSql); System.out.println(pageSql); if (dialect == com.swifts.frame.common.pagehelper.Dialect.sqlserver) { clearLocalPage(); } } /** * SqlSource * * @param ms * @throws Throwable */ public void processMappedStatement(MappedStatement ms) throws Throwable { SqlSource sqlSource = ms.getSqlSource(); MetaObject msObject = SystemMetaObject.forObject(ms); SqlSource pageSqlSource; if (sqlSource instanceof StaticSqlSource) { pageSqlSource = new PageStaticSqlSource((StaticSqlSource) sqlSource); } else if (sqlSource instanceof RawSqlSource) { pageSqlSource = new PageRawSqlSource((RawSqlSource) sqlSource); } else if (sqlSource instanceof ProviderSqlSource) { pageSqlSource = new PageProviderSqlSource((ProviderSqlSource) sqlSource); } else if (sqlSource instanceof DynamicSqlSource) { pageSqlSource = new PageDynamicSqlSource((DynamicSqlSource) sqlSource); } else { throw new RuntimeException("?[" + sqlSource.getClass() + "]SqlSource"); } msObject.setValue("sqlSource", pageSqlSource); //count??CountMS msCountMap.put(ms.getId(), MSUtils.newCountMappedStatement(ms)); } /** * ?? * * @param args * @return Page */ public com.swifts.frame.common.pagehelper.Page getPage(Object[] args) { com.swifts.frame.common.pagehelper.Page page = getLocalPage(); if (page == null || page.isOrderByOnly()) { com.swifts.frame.common.pagehelper.Page oldPage = page; //?,page.isOrderByOnly()true?? if ((args[2] == null || args[2] == RowBounds.DEFAULT) && page != null) { return oldPage; } if (args[2] instanceof RowBounds && args[2] != RowBounds.DEFAULT) { RowBounds rowBounds = (RowBounds) args[2]; if (offsetAsPageNum) { page = new com.swifts.frame.common.pagehelper.Page(rowBounds.getOffset(), rowBounds.getLimit(), rowBoundsWithCount); } else { page = new com.swifts.frame.common.pagehelper.Page( new int[] { rowBounds.getOffset(), rowBounds.getLimit() }, rowBoundsWithCount); //offsetAsPageNum=falsePageNum?reasonablefalse page.setReasonable(false); } } else { try { page = getPageFromObject(args[1]); } catch (Exception e) { return null; } } if (oldPage != null) { page.setOrderBy(oldPage.getOrderBy()); } setLocalPage(page); } //?? if (page.getReasonable() == null) { page.setReasonable(reasonable); } //truepagesize0RowBoundslimit=0? if (page.getPageSizeZero() == null) { page.setPageSizeZero(pageSizeZero); } return page; } /** * Mybatis?Threadlocal * * @param invocation ? * @return * @throws Throwable */ public Object processPage(Invocation invocation) throws Throwable { try { Object result = _processPage(invocation); return result; } finally { clearLocalPage(); } } /** * Mybatis * * @param invocation ? * @return * @throws Throwable */ private Object _processPage(Invocation invocation) throws Throwable { final Object[] args = invocation.getArgs(); com.swifts.frame.common.pagehelper.Page page = null; //????Page if (supportMethodsArguments) { page = getPage(args); } //? RowBounds rowBounds = (RowBounds) args[2]; //??page == null??? if ((supportMethodsArguments && page == null) //???LocalPageRowBounds?? || (!supportMethodsArguments && SqlUtil.getLocalPage() == null && rowBounds == RowBounds.DEFAULT)) { return invocation.proceed(); } else { //???page==null?? if (!supportMethodsArguments && page == null) { page = getPage(args); } return doProcessPage(invocation, page, args); } } /** * ??? * * @param page * @return */ private boolean isQueryOnly(com.swifts.frame.common.pagehelper.Page page) { return page.isOrderByOnly() || ((page.getPageSizeZero() != null && page.getPageSizeZero()) && page.getPageSize() == 0); } /** * ?? * * @param page * @param invocation * @return * @throws Throwable */ private com.swifts.frame.common.pagehelper.Page doQueryOnly(com.swifts.frame.common.pagehelper.Page page, Invocation invocation) throws Throwable { page.setCountSignal(null); //? Object result = invocation.proceed(); //? page.addAll((List) result); // page.setPageNum(1); //?pageSize=total page.setPageSize(page.size()); //??total page.setTotal(page.size()); //?Page - ??? return page; } /** * Mybatis * * @param invocation ? * @return * @throws Throwable */ private com.swifts.frame.common.pagehelper.Page doProcessPage(Invocation invocation, Page page, Object[] args) throws Throwable { //?RowBounds? RowBounds rowBounds = (RowBounds) args[2]; //?ms MappedStatement ms = (MappedStatement) args[0]; //?PageSqlSource if (!isPageSqlSource(ms)) { processMappedStatement(ms); } //?parser????setThreadLocal??? ((PageSqlSource) ms.getSqlSource()).setParser(parser); //RowBounds-?Mybatis args[2] = RowBounds.DEFAULT; //?? pageSizeZero if (isQueryOnly(page)) { return doQueryOnly(page, invocation); } //?total??count if (page.isCount()) { page.setCountSignal(Boolean.TRUE); //?MS args[0] = msCountMap.get(ms.getId()); // Object result = invocation.proceed(); //ms args[0] = ms; // page.setTotal((Integer) ((List) result).get(0)); if (page.getTotal() == 0) { return page; } } else { page.setTotal(-1l); } //pageSize>0pageSize<=0???count if (page.getPageSize() > 0 && ((rowBounds == RowBounds.DEFAULT && page.getPageNum() > 0) || rowBounds != RowBounds.DEFAULT)) { //?MappedStatement?qs page.setCountSignal(null); BoundSql boundSql = ms.getBoundSql(args[1]); args[1] = parser.setPageParameter(ms, args[1], boundSql, page); page.setCountSignal(Boolean.FALSE); // Object result = invocation.proceed(); //? page.addAll((List) result); } // return page; } public void setOffsetAsPageNum(boolean offsetAsPageNum) { this.offsetAsPageNum = offsetAsPageNum; } public void setRowBoundsWithCount(boolean rowBoundsWithCount) { this.rowBoundsWithCount = rowBoundsWithCount; } public void setPageSizeZero(boolean pageSizeZero) { this.pageSizeZero = pageSizeZero; } public void setReasonable(boolean reasonable) { this.reasonable = reasonable; } public void setSupportMethodsArguments(boolean supportMethodsArguments) { this.supportMethodsArguments = supportMethodsArguments; } public void setParams(String params) { PARAMS.put("pageNum", "pageNum"); PARAMS.put("pageSize", "pageSize"); PARAMS.put("count", "countSql"); PARAMS.put("orderBy", "orderBy"); PARAMS.put("reasonable", "reasonable"); PARAMS.put("pageSizeZero", "pageSizeZero"); if (StringUtil.isNotEmpty(params)) { String[] ps = params.split("[;|,|&]"); for (String s : ps) { String[] ss = s.split("[=|:]"); if (ss.length == 2) { PARAMS.put(ss[0], ss[1]); } } } } public void setProperties(Properties p) { //offsetPageNum String offsetAsPageNum = p.getProperty("offsetAsPageNum"); this.offsetAsPageNum = Boolean.parseBoolean(offsetAsPageNum); //RowBounds???count String rowBoundsWithCount = p.getProperty("rowBoundsWithCount"); this.rowBoundsWithCount = Boolean.parseBoolean(rowBoundsWithCount); //truepagesize0RowBoundslimit=0? String pageSizeZero = p.getProperty("pageSizeZero"); this.pageSizeZero = Boolean.parseBoolean(pageSizeZero); //??true?????false?? String reasonable = p.getProperty("reasonable"); this.reasonable = Boolean.parseBoolean(reasonable); //??????false String supportMethodsArguments = p.getProperty("supportMethodsArguments"); this.supportMethodsArguments = Boolean.parseBoolean(supportMethodsArguments); //offsetAsPageNum=false? //? setParams(p.getProperty("params")); } public void setSqlUtilConfig(SqlUtilConfig config) { this.offsetAsPageNum = config.isOffsetAsPageNum(); this.rowBoundsWithCount = config.isRowBoundsWithCount(); this.pageSizeZero = config.isPageSizeZero(); this.reasonable = config.isReasonable(); this.supportMethodsArguments = config.isSupportMethodsArguments(); setParams(config.getParams()); } }