private void pagination(Invocation invocation, StatementHandler target) throws SQLException { final MetaObject metaStatementHandler = getMetaObject(target); final BoundSql boundSql = target.getBoundSql(); Page<?> page = PAGE_THREAD_LOCAL.get(); if (page == null) { page = findPageParameter(boundSql.getParameterObject()); } // 如果传入的参数中有分页对象且sql语句中有select,才做分页处理 String sql = boundSql.getSql().toLowerCase(); if (sql.startsWith("select") && page != null) { // 采用物理分页后,就不需要mybatis的内存分页了,所以重置下面的两个参数 metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET); metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT); // 设置分页对象里的总记录数和总页数 Connection connection = (Connection) invocation.getArgs()[0]; MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement"); if (page.isCountTotal()) { int recordsTotal = getTotalCount(sql, connection, mappedStatement, boundSql); page.setTotalNum(recordsTotal); } // 最后重写sql String pageSql = buildPageSql(sql, page); metaStatementHandler.setValue("delegate.boundSql.sql", pageSql); } }
/** * 生成特定数据库的分页语句 * * @param sql * @param page * @return */ private String buildPageSql(String sql, Page<?> page) { if (page == null || dialect == null || dialect.equals("")) { return sql; } StringBuilder sb = new StringBuilder(); int startRow = page.getOffset(); if ("mysql".equals(dialect)) { sb.append(sql); sb.append(" limit ").append(startRow).append(",").append(page.getLimit()); } else if ("hsqldb".equals(dialect)) { sb.append("select limit "); sb.append(startRow); sb.append(" "); sb.append(page.getLimit()); sb.append(" "); sb.append(sql.substring(6)); } else if ("oracle".equals(dialect)) { sb.append("select * from (select tmp_tb.*,ROWNUM row_id from ("); sb.append(sql); sb.append(") tmp_tb where ROWNUM<="); sb.append(startRow + page.getLimit()); sb.append(") where row_id>"); sb.append(startRow); } else { throw new IllegalArgumentException("SelectInterceptor error:does not support " + dialect); } return sb.toString(); }
@SuppressWarnings({"rawtypes", "unchecked"}) private void autoMap(Invocation invocation, String name) throws ClassNotFoundException { final Object[] queryArgs = invocation.getArgs(); final MappedStatement ms = (MappedStatement) queryArgs[0]; final Object parameter = queryArgs[1]; String statementId = ms.getId(); MapperMeta meta = getMapperMeta(ms.getConfiguration(), statementId); if (meta.isFillEntity()) { // 将泛型类加入到参数中供CrudTemplate使用 if (parameter != null) { Map map; if (parameter instanceof Map) { map = (HashMap) parameter; map.put(CrudProvider.CLASS_KEY, meta.getEntity()); } else { map = new HashMap(); map.put(CrudProvider.PARA_KEY, parameter); map.put(CrudProvider.CLASS_KEY, meta.getEntity()); } queryArgs[1] = map; } else { queryArgs[1] = meta.getEntity(); } } if (meta.isFillResultMap()) { MetaObject metaMappedStatement = getMetaObject(ms); metaMappedStatement.setValue("resultMaps", meta.getResultMaps()); } if (name.equals("query")) { final RowBounds rowBounds = (RowBounds) queryArgs[2]; if (rowBounds == null || rowBounds == RowBounds.DEFAULT) { Page p = findPageParameter(queryArgs[1]); if (p != null) { queryArgs[2] = new RowBounds(p.getOffset(), p.getLimit()); } } } }
@SuppressWarnings({"rawtypes", "unchecked"}) @Override public Object intercept(Invocation invocation) throws Throwable { final String name = invocation.getMethod().getName(); final Object target = invocation.getTarget(); if (target instanceof StatementHandler) { pagination(invocation, (StatementHandler) target); } else if (target instanceof Executor) { autoMap(invocation, name); } else if (target instanceof ResultSetHandler) { Object result = invocation.proceed(); if (result instanceof List) { Page page = PAGE_THREAD_LOCAL.get(); if (page != null) { page.addAll((List) result); PAGE_THREAD_LOCAL.remove(); return page; } } return result; } return invocation.proceed(); }