分页查询<br>
查询条件为多个key value对表示，默认key = value，如果使用其它条件可以使用：where.put("key", " &gt; 1")，value也可以传Condition对象，key被忽略

@param where 条件实体类（包含表名）
@param page 页码
@param numPerPage 每页条目数
@return 分页结果集
@throws SQLException SQL执行异常
@since 3.2.2
971924
public PageResult<Entity> page(Entity where, int page, int numPerPage) throws SQLException {
		return this.page(where, new Page(page, numPerPage));
	}
182328
function Page(page) {
  if (!page) page = {};
  for (var key in page) this[key] = page[key];
  if (!this.hasOwnProperty('idx')) this.idx = 0;
  if (!this.hasOwnProperty('total')) this.total = 1;
  if (!this.hasOwnProperty('current')) {
    this.current = this.total;
  }
}
458
private static function _setWhere($where, QueryBuilder $query, string $primaryKey = "id") : QueryBuilder
    {
        if(!is_array($where)) {
            return $query->where([
                $primaryKey => $where
            ]);
        }

        $columns = $where;

        unset($columns["ORDER BY"]);
        unset($columns["LIMIT"]);
        unset($columns["OFFSET"]);

        if(!empty($columns)) {
            $query->where($columns);
        }

        if(isset($where["ORDER BY"])) {
            $order = $where["ORDER BY"];
            if(!is_array($order)) {
                $order = [$order];
            }

            $query->order(... $order);
        }
        if(isset($where["LIMIT"])) {
            $limit = $where["LIMIT"];
            if(!is_array($limit)) {
                $limit = [$limit];
            }

            $query->limit(... $limit);
        }
        if(isset($where["OFFSET"])) {
            $query->offset($where["OFFSET"]);
        }

        return $query;
    }
90967
private static List<Map<String, Object>> handleResultSetToMapList(ResultSet result,
                                                                      List<Map<String, Object>> listProperties)
            throws SQLException {
        // 存放记录的信息
        Map<String, Object> property = null;

        // 获取结果集中的列名
        List<String> listColumns = DBUtils.getColumnLabels(result);

        // 存放记录
        while (result.next()) {
            property = new HashMap<String, Object>();
            // 将每条记录的列以及相应的列值存入一个Map对象中
            for (int i = 0; i < listColumns.size(); i++) {
                property.put(listColumns.get(i), result.getObject(i + 1));
            }
            // 将存入记录的每个map对象放入数组中
            listProperties.add(property);
        }
        return listProperties;
    }
182393
@Override
    public String pageSql(int pPageIndex, int pPageSize)
    {
        String tablename= ModelHelper.getTableName(this.getClass());
        String sql="select * from ${tablename} order by rev_";
        sql= StringUtil.replace(sql,"${tablename}",tablename);
        sql = PageSqlUtil.getPageDataSQL(sql,String.valueOf(pPageIndex),String.valueOf(pPageSize));
        return sql;
    }
401230
private static void addTable(Connection conn, PageContext pc, String name, Query query, boolean doSimpleTypes, ArrayList<String> usedTables)
	    throws SQLException, PageException {
	Statement stat;
	usedTables.add(name);
	stat = conn.createStatement();
	Key[] keys = CollectionUtil.keys(query);
	int[] types = query.getTypes();
	int[] innerTypes = toInnerTypes(types);
	// CREATE STATEMENT
	String comma = "";
	StringBuilder create = new StringBuilder("CREATE TABLE " + name + " (");
	StringBuilder insert = new StringBuilder("INSERT INTO  " + name + " (");
	StringBuilder values = new StringBuilder("VALUES (");
	for (int i = 0; i < keys.length; i++) {
	    String key = keys[i].getString();
	    String type = (doSimpleTypes) ? "VARCHAR_IGNORECASE" : toUsableType(types[i]);

	    create.append(comma + key);
	    create.append(" ");
	    create.append(type);
	    insert.append(comma + key);
	    values.append(comma + "?");
	    comma = ",";
	}
	create.append(")");
	insert.append(")");
	values.append(")");
	stat.execute(create.toString());
	PreparedStatement prepStat = conn.prepareStatement(insert.toString() + values.toString());

	// INSERT STATEMENT
	// HashMap integerTypes=getIntegerTypes(types);

	int count = query.getRecordcount();
	QueryColumn[] columns = new QueryColumn[keys.length];
	for (int i = 0; i < keys.length; i++) {
	    columns[i] = query.getColumn(keys[i]);
	}
	for (int y = 0; y < count; y++) {
	    for (int i = 0; i < keys.length; i++) {
		int type = innerTypes[i];
		Object value = columns[i].get(y + 1, null);

		// print.out("*** "+type+":"+Caster.toString(value));
		if (doSimpleTypes) {

		    prepStat.setObject(i + 1, Caster.toString(value));
		}
		else {
		    if (value == null) prepStat.setNull(i + 1, types[i]);
		    else if (type == BINARY) prepStat.setBytes(i + 1, Caster.toBinary(value));
		    else if (type == DATE) {
			// print.out(new java.util.Date(new
			// Date(DateCaster.toDateAdvanced(value,pc.getTimeZone()).getTime()).getTime()));

			prepStat.setTimestamp(i + 1, (value.equals("")) ? null : new Timestamp(DateCaster.toDateAdvanced(query.getAt(keys[i], y + 1), pc.getTimeZone()).getTime()));
			// prepStat.setObject(i+1,Caster.toDate(value,null));
			// prepStat.setDate(i+1,(value==null || value.equals(""))?null:new
			// Date(DateCaster.toDateAdvanced(value,pc.getTimeZone()).getTime()));
		    }
		    else if (type == TIME)
			prepStat.setTime(i + 1, (value.equals("")) ? null : new Time(DateCaster.toDateAdvanced(query.getAt(keys[i], y + 1), pc.getTimeZone()).getTime()));
		    else if (type == TIMESTAMP)
			prepStat.setTimestamp(i + 1, (value.equals("")) ? null : new Timestamp(DateCaster.toDateAdvanced(query.getAt(keys[i], y + 1), pc.getTimeZone()).getTime()));
		    else if (type == DOUBLE) prepStat.setDouble(i + 1, (value.equals("")) ? 0 : Caster.toDoubleValue(query.getAt(keys[i], y + 1)));
		    else if (type == INT) prepStat.setLong(i + 1, (value.equals("")) ? 0 : Caster.toLongValue(query.getAt(keys[i], y + 1)));
		    else if (type == STRING) prepStat.setObject(i + 1, Caster.toString(value));
		}

	    }
	    prepStat.execute();
	}

    }
1225435
private static <L extends Annotation> String defineLimitStatement(final SQLiteModelMethod method, final JQL result, Class<L> annotation, Map<JQLDynamicStatementType, String> dynamicReplace) {
		StringBuilder builder = new StringBuilder();

		int pageSize = AnnotationUtility.extractAsInt(method.getElement(), annotation, AnnotationAttributeType.PAGE_SIZE);
		if (pageSize > 0) {
			result.annotatedPageSize = true;
		}

		final One<String> pageDynamicName = new One<String>(null);
		forEachParameter(method, new OnMethodParameterListener() {

			@Override
			public void onMethodParameter(VariableElement methodParam) {
				if (methodParam.getAnnotation(BindSqlPageSize.class) != null) {
					pageDynamicName.value0 = methodParam.getSimpleName().toString();
					result.paramPageSize = pageDynamicName.value0;

					// CONSTRAINT: @BindSqlWhereArgs can be used only on
					// String[] parameter type
					AssertKripton.assertTrueOrInvalidTypeForAnnotationMethodParameterException(TypeUtility.isEquals(TypeName.INT, TypeUtility.typeName(methodParam)), method.getParent().getElement(),
							method.getElement(), methodParam, BindSqlPageSize.class);
				}

			}
		});

		if (pageSize > 0 || StringUtils.hasText(pageDynamicName.value0) || method.isPagedLiveData()) {
			builder.append(" " + LIMIT_KEYWORD + " ");

			if (pageSize > 0) {
				builder.append(pageSize);
			} else {
				String temp0 = "#{" + JQLDynamicStatementType.DYNAMIC_PAGE_SIZE + "}";
				builder.append(temp0);
				dynamicReplace.put(JQLDynamicStatementType.DYNAMIC_PAGE_SIZE, temp0);
			}

			// define replacement string for PAGE_SIZE
			String temp1 = " " + OFFSET_KEYWORD + " #{" + JQLDynamicStatementType.DYNAMIC_PAGE_OFFSET + "}";

			builder.append(temp1);
			dynamicReplace.put(JQLDynamicStatementType.DYNAMIC_PAGE_OFFSET, temp1);

		}

		return builder.toString();
	}
972506
public void in(Object key, Object value, Integer type) throws SQLException {
        if (key instanceof Integer) {
            if (type == null) {
                base.setObject((Integer) key, value);
            } else {
                base.setObject((Integer) key, value, type);
            }
        } else {
            if (type == null) {
                base.setObject((String) key, value);
            } else {
                base.setObject((String) key, value, type);
            }
        }
    }
607218
public String convertToPageSql(String sql, Integer offset, Integer limit) {
        //解析SQL
        Statement stmt;
        try {
            stmt = CCJSqlParserUtil.parse(sql);
        } catch (Throwable e) {
            throw new PageException("不支持该SQL转换为分页查询!", e);
        }
        if (!(stmt instanceof Select)) {
            throw new PageException("分页语句必须是Select查询!");
        }
        //获取分页查询的select
        Select pageSelect = getPageSelect((Select) stmt);
        String pageSql = pageSelect.toString();
        //缓存移到外面了，所以不替换参数
        if (offset != null) {
            pageSql = pageSql.replace(START_ROW, String.valueOf(offset));
        }
        if (limit != null) {
            pageSql = pageSql.replace(PAGE_SIZE, String.valueOf(limit));
        }
        return pageSql;
    }
1283099
public <T> T page(Connection conn, Collection<String> fields, Entity where, int pageNumber, int numPerPage, RsHandler<T> rsh) throws SQLException {
		return page(conn, fields, where, new Page(pageNumber, numPerPage), rsh);
	}
68760
public final void mWHERE() throws RecognitionException {
		try {
			int _type = WHERE;
			int _channel = DEFAULT_TOKEN_CHANNEL;
			// druidG.g:629:8: ( ( 'WHERE' | 'where' ) )
			// druidG.g:629:10: ( 'WHERE' | 'where' )
			{
			// druidG.g:629:10: ( 'WHERE' | 'where' )
			int alt18=2;
			int LA18_0 = input.LA(1);
			if ( (LA18_0=='W') ) {
				alt18=1;
			}
			else if ( (LA18_0=='w') ) {
				alt18=2;
			}

			else {
				NoViableAltException nvae =
					new NoViableAltException("", 18, 0, input);
				throw nvae;
			}

			switch (alt18) {
				case 1 :
					// druidG.g:629:11: 'WHERE'
					{
					match("WHERE"); 

					}
					break;
				case 2 :
					// druidG.g:629:19: 'where'
					{
					match("where"); 

					}
					break;

			}

			}

			state.type = _type;
			state.channel = _channel;
		}
		finally {
			// do for sure before leaving
		}
	}
26905
final public function page($page = 1, $num = 10)
    {
        $page = max($page, 1);
        $start = ($page - 1) * $num;
        $this->limit($num, $start);
        $bak = $this->_sql;
        $infos = $this->_getAll();

        $this->_sql = $bak;
        $querySql = $this->sql;
        $total = $this->count();
        //重新组装两个SQL
        $this->sql = "Rows:" . $querySql . "\n Count:" . $this->sql;
        return [$infos, $total];
    }
755368
public LLIndexPage locatePageForKey(long key, long value, boolean allowCreate) {
		if (isLeaf) {
			return this;
		}
		if (nEntries == -1 && !allowCreate) {
			return null;
		}

		//The stored value[i] is the min-values of the according page[i+1} 
        int pos = binarySearch(0, nEntries, key, value);
        if (pos >= 0) {
            //pos of matching key
            pos++;
        } else {
            pos = -(pos+1);
        }
        //TODO use weak refs
        //read page before that value
        LLIndexPage page = (LLIndexPage) readOrCreatePage(pos, allowCreate);
        return page.locatePageForKey(key, value, allowCreate);
	}
292289
public void put(String key, Character value) {
		if (this.compiledStatement != null) {
			if (value == null) {
				this.compiledStatement.bindNull(compiledStatementBindIndex++);
			} else {
				compiledStatement.bindLong(compiledStatementBindIndex++, Character.getNumericValue(value));
			}
		} else if (values != null) {
			values.put(key, Character.getNumericValue(value));
			return;
		}

		names.add(key);
		// values.put(key, value);
		args.add(value);
		valueType.add(ParamType.CHARACTER);
	}
815764
public String findByPage(final Map<String, Object> parameter) {
    return new SQL() {
      {
        Class<?> clazz = (Class<?>) parameter.get(CLASS_KEY);
        SELECT("*");
        FROM(EntityUtil.getTableName(clazz));
        if (parameter.containsKey(WHERE_KEY)) {
          WHERE((String) parameter.get(WHERE_KEY));
        }
        if (parameter.containsKey(ORDER_KEY)) {
          ORDER_BY((String) parameter.get(ORDER_KEY));
        }
        if (parameter.containsKey(GROUP_KEY)) {
          GROUP_BY((String) parameter.get(GROUP_KEY));
        }
      }
    }.toString();
  }
866901
public static String call(PageContext pc, Object var, boolean serializeQueryByColumns) throws PageException {
	return _call(pc, var, serializeQueryByColumns, pc.getWebCharset());
    }
224853
function where(column, operator, value) {

    // Support "where true || where false"
    if (column === false || column === true) {
      return this.where(1, '=', column ? 1 : 0);
    }

    // Check if the column is a function, in which case it's
    // a where statement wrapped in parens.
    if (typeof column === 'function') {
      return this.whereWrapped(column);
    }

    // Allow a raw statement to be passed along to the query.
    if (column instanceof Raw && arguments.length === 1) {
      return this.whereRaw(column);
    }

    // Allows `where({id: 2})` syntax.
    if (typeof column === 'object' && !(column instanceof Raw)) {
      return this._objectWhere(column);
    }

    // Enable the where('key', value) syntax, only when there
    // are explicitly two arguments passed, so it's not possible to
    // do where('key', '!=') and have that turn into where key != null
    if (arguments.length === 2) {
      value = operator;
      operator = '=';

      // If the value is null, and it's a two argument query,
      // we assume we're going for a `whereNull`.
      if (value === null) {
        return this.whereNull(column);
      }
    }

    // lower case the operator for comparison purposes
    var checkOperator = ('' + operator).toLowerCase().trim();

    // If there are 3 arguments, check whether 'in' is one of them.
    if (arguments.length === 3) {
      if (checkOperator === 'in' || checkOperator === 'not in') {
        return this._not(checkOperator === 'not in').whereIn(arguments[0], arguments[2]);
      }
      if (checkOperator === 'between' || checkOperator === 'not between') {
        return this._not(checkOperator === 'not between').whereBetween(arguments[0], arguments[2]);
      }
    }

    // If the value is still null, check whether they're meaning
    // where value is null
    if (value === null) {

      // Check for .where(key, 'is', null) or .where(key, 'is not', 'null');
      if (checkOperator === 'is' || checkOperator === 'is not') {
        return this._not(checkOperator === 'is not').whereNull(column);
      }
    }

    // Push onto the where statement stack.
    this._statements.push({
      grouping: 'where',
      type: 'whereBasic',
      column: column,
      operator: operator,
      value: value,
      not: this._not(),
      bool: this._bool()
    });
    return this;
  }