├── .gitignore ├── deploy.sh ├── src ├── test │ ├── resources │ │ ├── sql │ │ │ └── scheml.sql │ │ ├── spring │ │ │ ├── test.properties │ │ │ └── test-context.xml │ │ ├── log4j.properties │ │ └── mapper │ │ │ └── ResourcesMapper.xml │ └── java │ │ └── org │ │ └── mybatis │ │ └── pagination │ │ ├── service │ │ ├── UtilsTest.java │ │ └── MapperTest.java │ │ ├── mapper │ │ └── ResourcesMapper.java │ │ └── domain │ │ ├── Resources.java │ │ └── ResourcesCriteria.java └── main │ └── java │ └── org │ └── mybatis │ └── pagination │ ├── dialect │ ├── DBMS.java │ ├── Dialect.java │ ├── db │ │ ├── SybaseDialect.java │ │ ├── DerbyDialect.java │ │ ├── H2Dialect.java │ │ ├── HSQLDialect.java │ │ ├── MySQLDialect.java │ │ ├── PostgreSQLDialect.java │ │ ├── SQLServerDialect.java │ │ ├── OracleDialect.java │ │ ├── DB2Dialect.java │ │ └── SQLServer2005Dialect.java │ └── DialectClient.java │ ├── extra │ └── MyBatisRepository.java │ ├── mvc │ ├── TableParam.java │ ├── DataTablesResultSet.java │ └── TableParamArgumentResolver.java │ ├── dto │ ├── datatables │ │ ├── SortDirection.java │ │ ├── SortField.java │ │ ├── SearchField.java │ │ └── PagingCriteria.java │ └── PageMyBatis.java │ ├── helpers │ ├── StringHelper.java │ └── CountHelper.java │ ├── PagingParametersFinder.java │ ├── PaginationExecutor.java │ └── PaginationInterceptor.java ├── LICENSE ├── Readme.md └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | *.iml 3 | *.class 4 | target/* 5 | .idea 6 | /src/main/java/org/.DS_Store 7 | .DS_Store -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | /Users/yfyang/Applications/apache-maven-3.0.5/bin/mvn clean deploy -Dmaven.test.skip=true -------------------------------------------------------------------------------- /src/test/resources/sql/scheml.sql: -------------------------------------------------------------------------------- 1 | create table res 2 | ( 3 | id varchar(64) not null comment '主键', 4 | name varchar(120) comment '资源名称', 5 | type varchar(120) comment '资源类型', 6 | path varchar(120) comment '资源地址', 7 | action varchar(120) comment '资源请求', 8 | controller varchar(120) comment '资源控制', 9 | status tinyint comment '状态', 10 | primary key (id) 11 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;; -------------------------------------------------------------------------------- /src/test/java/org/mybatis/pagination/service/UtilsTest.java: -------------------------------------------------------------------------------- 1 | package org.mybatis.pagination.service; 2 | 3 | import com.google.common.base.CaseFormat; 4 | import org.junit.Test; 5 | 6 | /** 7 | *

8 | * . 9 | *

10 | * 11 | * @author walter yang 12 | * @version 1.0 2013-09-24 12:20 AM 13 | * @since JDK 1.5 14 | */ 15 | public class UtilsTest { 16 | 17 | @Test 18 | public void testHump() throws Exception { 19 | 20 | System.out.println( CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, "helloDoMyword")); 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dialect/DBMS.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.dialect; 6 | 7 | /** 8 | *

9 | * 数据库类型. 10 | *

11 | * 12 | * @author poplar.yfyang 13 | * @version 1.0 2012-05-08 上午11:36 14 | * @since JDK 1.5 15 | */ 16 | public enum DBMS { 17 | MYSQL, 18 | ORACLE, 19 | DB2, 20 | H2, 21 | HSQL, 22 | POSTGRE, 23 | SQLSERVER, 24 | SQLSERVER2005, 25 | SYBASE, 26 | /** 27 | * 自定义 28 | */ 29 | EX 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/extra/MyBatisRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.extra; 6 | 7 | import java.lang.annotation.ElementType; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.RetentionPolicy; 10 | import java.lang.annotation.Target; 11 | 12 | /** 13 | *

14 | * 标识MyBatis的DAO,方便{@link org.mybatis.spring.mapper.MapperScannerConfigurer}的扫描。. 15 | *

16 | * 17 | * @author poplar.yfyang 18 | * @version 1.0 2012-10-27 7:05 PM 19 | * @since JDK 1.5 20 | */ 21 | @Retention(RetentionPolicy.RUNTIME) 22 | @Target(ElementType.TYPE) 23 | public @interface MyBatisRepository { 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/mvc/TableParam.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.mvc; 6 | 7 | import java.lang.annotation.Documented; 8 | import java.lang.annotation.ElementType; 9 | import java.lang.annotation.Retention; 10 | import java.lang.annotation.RetentionPolicy; 11 | import java.lang.annotation.Target; 12 | 13 | /** 14 | *

15 | * Spring MVC argument resolver annotation. 16 | *

17 | * 18 | * @author mumu@yfyang 19 | * @version 1.0 2013-09-05 10:43 PM 20 | * @since JDK 1.5 21 | */ 22 | @Target(ElementType.PARAMETER) 23 | @Retention(RetentionPolicy.RUNTIME) 24 | @Documented 25 | public @interface TableParam { 26 | } 27 | -------------------------------------------------------------------------------- /src/test/resources/spring/test.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2011-2012 NOO.com. All Rights Reserved. 3 | # This software for customer relationship management system, developed by Noo team. 4 | # Software code and design for the team, copy rights reserved. 5 | # 6 | driverClass=com.mysql.jdbc.Driver 7 | jdbcurl=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8 8 | username=rhea 9 | password=rhea@123 10 | minPoolSize=10 11 | acquireRetryAttempts=50 12 | idleConnectionTestPeriod=60 13 | acquireIncrement=3 14 | maxIdleTime=60 15 | initialPoolSize=10 16 | maxPoolSize=100 17 | # \u4E8B\u52A1\u4F20\u64AD\u4EE5\u53CA\u9694\u79BB\u7EA7\u522B 18 | transaction.propagation=REQUIRED 19 | transaction.level=ISOLATION_READ_UNCOMMITTED 20 | 21 | database_dialect=MYSQL 22 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dialect/Dialect.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.dialect; 6 | 7 | /** 8 | * 类似hibernate的Dialect,但只精简出分页部分 9 | * 10 | * @author poplar.yfyang 11 | * @version 1.0 2011-11-18 下午12:31 12 | * @since JDK 1.5 13 | */ 14 | public interface Dialect { 15 | 16 | /** 17 | * 数据库本身是否支持分页当前的分页查询方式 18 | * 如果数据库不支持的话,则不进行数据库分页 19 | * 20 | * @return true:支持当前的分页查询方式 21 | */ 22 | public boolean supportsLimit(); 23 | 24 | /** 25 | * 将sql转换为分页SQL,分别调用分页sql 26 | * 27 | * @param sql SQL语句 28 | * @param offset 开始条数 29 | * @param limit 每页显示多少纪录条数 30 | * @return 分页查询的sql 31 | */ 32 | public String getLimitString(String sql, int offset, int limit); 33 | 34 | /** 35 | * 将sql转换为总记录数SQL 36 | * @param sql SQL语句 37 | * @return 总记录数的sql 38 | */ 39 | public String getCountString(String sql); 40 | } 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 yfyang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2011-2012 NOO.com. All Rights Reserved. 3 | # This software for customer relationship management system, developed by Noo team. 4 | # Software code and design for the team, copy rights reserved. 5 | # 6 | log4j.rootLogger = DEBUG , stdout 7 | 8 | ### print _log to console ### 9 | log4j.appender.stdout = org.apache.log4j.ConsoleAppender 10 | log4j.appender.stdout.Target = System.out 11 | log4j.appender.stdout.layout = org.apache.log4j.PatternLayout 12 | log4j.appender.stdout.layout.ConversionPattern = %d %p [%c] - <%m>%n 13 | 14 | # SqlMap logging configuration... 15 | log4j.logger.com.ibatis=debug 16 | log4j.logger.com.ibatis.db=debug 17 | log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=debug 18 | log4j.logger.com.ibatis.sqlmap.engine.cache.CacheModel=debug 19 | log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientImpl=debug 20 | log4j.logger.com.ibatis.sqlmap.engine.builder.xml.SqlMapParser=debug 21 | log4j.logger.com.ibatis.common.util.StopWatch=debug 22 | 23 | 24 | log4j.logger.java.sql.Connection=debug 25 | log4j.logger.java.sql.Statement=error 26 | log4j.logger.java.sql.PreparedStatement=debug 27 | log4j.logger.java.sql.ResultSet=error 28 | 29 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dto/datatables/SortDirection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.dto.datatables; 6 | 7 | /** 8 | *

9 | * sort's direction. 10 | *

11 | * 12 | * @author mumu@yfyang 13 | * @version 1.0 2013-09-05 10:41 PM 14 | * @since JDK 1.5 15 | */ 16 | public enum SortDirection { 17 | /** 18 | * The ASC. 19 | */ 20 | ASC("asc"), 21 | /** 22 | * The DESC. 23 | */ 24 | DESC("desc"); 25 | private String direction; 26 | 27 | private SortDirection(String direction) { 28 | this.direction = direction; 29 | } 30 | 31 | /** 32 | * Value of case insensitive. 33 | * 34 | * @param value the value 35 | * @return the sort direction 36 | */ 37 | public static SortDirection valueOfCaseInsensitive(String value) { 38 | String valueUpper = value.toUpperCase(); 39 | return SortDirection.valueOf(valueUpper); 40 | } 41 | 42 | /** 43 | * Gets direction. 44 | * 45 | * @return the direction 46 | */ 47 | public String getDirection() { 48 | return this.direction; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dto/datatables/SortField.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.dto.datatables; 6 | 7 | /** 8 | *

9 | * the sort's filed define. 10 | *

11 | * 12 | * @author mumu@yfyang 13 | * @version 1.0 2013-09-05 10:39 PM 14 | * @since JDK 1.5 15 | */ 16 | public final class SortField { 17 | /** field name */ 18 | private final String field; 19 | /** sort direction */ 20 | private final SortDirection direction; 21 | 22 | /** 23 | * Instantiates a new Sort field. 24 | * 25 | * @param field the field 26 | * @param direction the direction 27 | */ 28 | public SortField(String field, SortDirection direction) { 29 | this.field = field; 30 | this.direction = direction; 31 | } 32 | 33 | /** 34 | * Instantiates a new Sort field. 35 | * 36 | * @param field the field 37 | * @param direction the direction 38 | */ 39 | public SortField(String field, String direction) { 40 | this.field = field; 41 | this.direction = SortDirection.valueOfCaseInsensitive(direction); 42 | } 43 | 44 | /** 45 | * Gets field. 46 | * 47 | * @return the field 48 | */ 49 | public String getField() { 50 | return field; 51 | } 52 | 53 | /** 54 | * Gets direction. 55 | * 56 | * @return the direction 57 | */ 58 | public SortDirection getDirection() { 59 | return direction; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dialect/db/SybaseDialect.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.dialect.db; 6 | 7 | import org.mybatis.pagination.dialect.Dialect; 8 | 9 | /** 10 | * Sybase数据库分页方言实现。 11 | * 还未实现 12 | * 13 | * @author poplar.yfyang 14 | * @version 1.0 2010-10-10 下午12:31 15 | * @since JDK 1.5 16 | */ 17 | public class SybaseDialect implements Dialect { 18 | 19 | public boolean supportsLimit() { 20 | return false; 21 | } 22 | 23 | @Override 24 | public String getLimitString(String sql, int offset, int limit) { 25 | return null; 26 | } 27 | 28 | /** 29 | * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. 30 | *
31 |      * 如mysql
32 |      * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回
33 |      * select * from user limit :offset,:limit
34 |      * 
35 | * 36 | * @param sql 实际SQL语句 37 | * @param offset 分页开始纪录条数 38 | * @param offsetPlaceholder 分页开始纪录条数-占位符号 39 | * @param limit 分页每页显示纪录条数 40 | * @param limitPlaceholder 分页纪录条数占位符号 41 | * @return 包含占位符的分页sql 42 | */ 43 | public String getLimitString(String sql, int offset, String offsetPlaceholder, int limit, String limitPlaceholder) { 44 | throw new UnsupportedOperationException("paged queries not supported"); 45 | } 46 | 47 | @Override 48 | public String getCountString(String querySqlString) { 49 | String sql = SQLServer2005Dialect.getNonOrderByPart(querySqlString); 50 | return "select count(1) from (" + sql + ") as tmp_count"; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dialect/db/DerbyDialect.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.dialect.db; 6 | 7 | import org.mybatis.pagination.dialect.Dialect; 8 | 9 | /** 10 | * @author poplar.yfyang 11 | * @version 1.0 2010-10-10 下午12:31 12 | * @since JDK 1.5 13 | */ 14 | public class DerbyDialect implements Dialect { 15 | @Override 16 | public boolean supportsLimit() { 17 | return false; 18 | } 19 | 20 | @Override 21 | public String getLimitString(String sql, int offset, int limit) { 22 | // return getLimitString(sql,offset,Integer.toString(offset),limit,Integer.toString(limit)); 23 | throw new UnsupportedOperationException("paged queries not supported"); 24 | } 25 | 26 | /** 27 | * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. 28 | *
29 |      * 如mysql
30 |      * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回
31 |      * select * from user limit :offset,:limit
32 |      * 
33 | * 34 | * @param sql 实际SQL语句 35 | * @param offset 分页开始纪录条数 36 | * @param offsetPlaceholder 分页开始纪录条数-占位符号 37 | * @param limit 分页每页显示纪录条数 38 | * @param limitPlaceholder 分页纪录条数占位符号 39 | * @return 包含占位符的分页sql 40 | */ 41 | public String getLimitString(String sql, int offset, String offsetPlaceholder, int limit, String limitPlaceholder) { 42 | throw new UnsupportedOperationException("paged queries not supported"); 43 | } 44 | 45 | @Override 46 | public String getCountString(String querySqlString) { 47 | String sql = SQLServer2005Dialect.getNonOrderByPart(querySqlString); 48 | return "select count(1) from (" + sql + ") as tmp_count"; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dialect/db/H2Dialect.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.dialect.db; 6 | 7 | import org.mybatis.pagination.dialect.Dialect; 8 | 9 | /** 10 | * A dialect compatible with the H2 database. 11 | * 12 | * @author poplar.yfyang 13 | * @version 1.0 2010-10-10 下午12:31 14 | * @since JDK 1.5 15 | */ 16 | public class H2Dialect implements Dialect { 17 | 18 | public boolean supportsLimit() { 19 | return true; 20 | } 21 | 22 | /** 23 | * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. 24 | *
25 |      * 如mysql
26 |      * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回
27 |      * select * from user limit :offset,:limit
28 |      * 
29 | * 30 | * @param sql 实际SQL语句 31 | * @param offset 分页开始纪录条数 32 | * @param offsetPlaceholder 分页开始纪录条数-占位符号 33 | * @param limit 分页每页显示纪录条数 34 | * @param limitPlaceholder 分页纪录条数占位符号 35 | * @return 包含占位符的分页sql 36 | */ 37 | private String getLimitString(String sql, int offset, String offsetPlaceholder, int limit, String limitPlaceholder) { 38 | return sql + ((offset > 0) ? " limit " + limitPlaceholder + " offset " 39 | + offsetPlaceholder : " limit " + limitPlaceholder); 40 | } 41 | 42 | @Override 43 | public String getLimitString(String sql, int offset, int limit) { 44 | return getLimitString(sql, offset, Integer.toString(offset), limit, Integer.toString(limit)); 45 | } 46 | 47 | @Override 48 | public String getCountString(String querySqlString) { 49 | String sql = SQLServer2005Dialect.getNonOrderByPart(querySqlString); 50 | return "select count(1) from (" + sql + ") as tmp_count"; 51 | } 52 | } -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/mvc/DataTablesResultSet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.mvc; 6 | 7 | import java.util.Collections; 8 | import java.util.List; 9 | 10 | import org.mybatis.pagination.dto.PageMyBatis; 11 | 12 | /** 13 | *

14 | * . 15 | *

16 | * 17 | * @author mumu@yfyang 18 | * @version 1.0 2013-09-05 10:48 PM 19 | * @since JDK 1.5 20 | */ 21 | public final class DataTablesResultSet { 22 | private final int sEcho; 23 | private final long iTotalRecords; 24 | private final long iTotalDisplayRecords; 25 | private final List aaData; 26 | 27 | /** 28 | * Instantiates a new Data tables result set. 29 | * 30 | * @param sEcho the pc 31 | * @param rs the rs 32 | */ 33 | public DataTablesResultSet(int sEcho, PageMyBatis rs) { 34 | this.sEcho = sEcho; 35 | this.aaData = rs; 36 | this.iTotalRecords = rs.getTotal(); 37 | this.iTotalDisplayRecords = rs.getTotal(); 38 | } 39 | 40 | /** 41 | * Gets echo. 42 | * 43 | * @return the echo 44 | */ 45 | public int getsEcho() { 46 | return sEcho; 47 | } 48 | 49 | /** 50 | * Gets total records. 51 | * 52 | * @return the total records 53 | */ 54 | public long getiTotalRecords() { 55 | return iTotalRecords; 56 | } 57 | 58 | /** 59 | * Gets total display records. 60 | * 61 | * @return the total display records 62 | */ 63 | public long getiTotalDisplayRecords() { 64 | return iTotalDisplayRecords; 65 | } 66 | 67 | /** 68 | * Gets aa data. 69 | * 70 | * @return the aa data 71 | */ 72 | public List getAaData() { 73 | return Collections.unmodifiableList(aaData); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dialect/db/HSQLDialect.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.dialect.db; 6 | 7 | import org.mybatis.pagination.dialect.Dialect; 8 | 9 | /** 10 | * Dialect for HSQLDB 11 | * 12 | * @author poplar.yfyang 13 | * @version 1.0 2010-10-10 下午12:31 14 | * @since JDK 1.5 15 | */ 16 | public class HSQLDialect implements Dialect { 17 | @Override 18 | public boolean supportsLimit() { 19 | return true; 20 | } 21 | 22 | @Override 23 | public String getLimitString(String sql, int offset, int limit) { 24 | return getLimitString(sql, offset, Integer.toString(offset), 25 | Integer.toString(limit)); 26 | } 27 | 28 | /** 29 | * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. 30 | *
31 |      * 如mysql
32 |      * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回
33 |      * select * from user limit :offset,:limit
34 |      *
35 |      * select limit :offset,:limit * from user
36 |      * 
37 | * 38 | * @param sql 实际SQL语句 39 | * @param offset 分页开始纪录条数 40 | * @param offsetPlaceholder 分页开始纪录条数-占位符号 41 | * @param limitPlaceholder 分页纪录条数占位符号 42 | * @return 包含占位符的分页sql 43 | */ 44 | public String getLimitString(String sql, int offset, String offsetPlaceholder, String limitPlaceholder) { 45 | boolean hasOffset = offset > 0; 46 | return 47 | new StringBuffer(sql.length() + 10) 48 | .append(sql) 49 | .insert(sql.toLowerCase().indexOf("select") + 6, hasOffset ? " limit " + offsetPlaceholder + " " + limitPlaceholder : " top " + limitPlaceholder) 50 | .toString(); 51 | } 52 | 53 | @Override 54 | public String getCountString(String sql) { 55 | return "select count(*) from (" + sql + ") as tmp_count"; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dialect/db/MySQLDialect.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.dialect.db; 6 | 7 | import org.mybatis.pagination.dialect.Dialect; 8 | 9 | /** 10 | * Mysql方言的实现 11 | * 12 | * @author poplar.yfyang 13 | * @version 1.0 2010-10-10 下午12:31 14 | * @since JDK 1.5 15 | */ 16 | public class MySQLDialect implements Dialect { 17 | 18 | 19 | @Override 20 | public String getLimitString(String sql, int offset, int limit) { 21 | return getLimitString(sql, offset, Integer.toString(offset), 22 | Integer.toString(limit)); 23 | } 24 | 25 | public boolean supportsLimit() { 26 | return true; 27 | } 28 | 29 | /** 30 | * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. 31 | *
32 |      * 如mysql
33 |      * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回
34 |      * select * from user limit :offset,:limit
35 |      * 
36 | * 37 | * @param sql 实际SQL语句 38 | * @param offset 分页开始纪录条数 39 | * @param offsetPlaceholder 分页开始纪录条数-占位符号 40 | * @param limitPlaceholder 分页纪录条数占位符号 41 | * @return 包含占位符的分页sql 42 | */ 43 | public String getLimitString(String sql, int offset, String offsetPlaceholder, String limitPlaceholder) { 44 | StringBuilder stringBuilder = new StringBuilder(sql); 45 | stringBuilder.append(" limit "); 46 | if (offset > 0) { 47 | stringBuilder.append(offsetPlaceholder).append(",").append(limitPlaceholder); 48 | } else { 49 | stringBuilder.append(limitPlaceholder); 50 | } 51 | return stringBuilder.toString(); 52 | } 53 | 54 | @Override 55 | public String getCountString(String querySqlString) { 56 | String sql = SQLServer2005Dialect.getNonOrderByPart(querySqlString); 57 | return "select count(1) from (" + sql + ") as tmp_count"; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dialect/db/PostgreSQLDialect.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.dialect.db; 6 | 7 | import org.mybatis.pagination.dialect.Dialect; 8 | 9 | /** 10 | * Postgre Sql的方言实现 11 | * 12 | * @author poplar.yfyang 13 | * @version 1.0 2010-10-10 下午12:31 14 | * @since JDK 1.5 15 | */ 16 | public class PostgreSQLDialect implements Dialect { 17 | 18 | public boolean supportsLimit() { 19 | return true; 20 | } 21 | 22 | @Override 23 | public String getLimitString(String sql, int offset, int limit) { 24 | return getLimitString(sql, offset, Integer.toString(offset), 25 | Integer.toString(limit)); 26 | } 27 | 28 | /** 29 | * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. 30 | *
31 |      * 如mysql
32 |      * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回
33 |      * select * from user limit :offset,:limit
34 |      * 
35 | * 36 | * @param sql 实际SQL语句 37 | * @param offset 分页开始纪录条数 38 | * @param offsetPlaceholder 分页开始纪录条数-占位符号 39 | * @param limitPlaceholder 分页纪录条数占位符号 40 | * @return 包含占位符的分页sql 41 | */ 42 | public String getLimitString(String sql, int offset, 43 | String offsetPlaceholder, String limitPlaceholder) { 44 | StringBuilder pageSql = new StringBuilder().append(sql); 45 | pageSql = offset <= 0 46 | ? pageSql.append(" limit ").append(limitPlaceholder) : 47 | pageSql.append(" limit ").append(limitPlaceholder).append(" offset ").append(offsetPlaceholder); 48 | return pageSql.toString(); 49 | } 50 | 51 | @Override 52 | public String getCountString(String querySqlString) { 53 | String sql = SQLServer2005Dialect.getNonOrderByPart(querySqlString); 54 | return "select count(1) from (" + sql + ") as tmp_count"; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dto/datatables/SearchField.java: -------------------------------------------------------------------------------- 1 | package org.mybatis.pagination.dto.datatables; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | *

7 | * The DataTables search filed model. 8 | *

9 | * 10 | * @author walter yang 11 | * @version 1.0 2013-09-12 10:22 AM 12 | * @since JDK 1.5 13 | */ 14 | public class SearchField implements Serializable { 15 | 16 | private static final long serialVersionUID = -8493268499000005405L; 17 | /** field name */ 18 | private final String field; 19 | /** True if the individual column filter should be treated as a regular expression for advanced filtering, false if not */ 20 | private final boolean regex; 21 | /** Indicator for if a column is flagged as sortable or not on the client-side */ 22 | private final boolean searchable; 23 | /** search value. */ 24 | private final String value; 25 | 26 | /** 27 | * Instantiates a new Search field. 28 | * 29 | * @param field the field 30 | * @param regex the regex 31 | * @param searchable the searchable 32 | * @param value the value 33 | */ 34 | public SearchField(String field, boolean regex, boolean searchable, String value) { 35 | this.field = field; 36 | this.regex = regex; 37 | this.searchable = searchable; 38 | this.value = value; 39 | } 40 | 41 | /** 42 | * Gets value. 43 | * 44 | * @return the value 45 | */ 46 | public String getValue() { 47 | return value; 48 | } 49 | 50 | /** 51 | * Gets field. 52 | * 53 | * @return the field 54 | */ 55 | public String getField() { 56 | return field; 57 | } 58 | 59 | /** 60 | * Is regex. 61 | * 62 | * @return the boolean 63 | */ 64 | public boolean isRegex() { 65 | return regex; 66 | } 67 | 68 | /** 69 | * Is searchable. 70 | * 71 | * @return the boolean 72 | */ 73 | public boolean isSearchable() { 74 | return searchable; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dialect/db/SQLServerDialect.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.dialect.db; 6 | 7 | import org.mybatis.pagination.dialect.Dialect; 8 | 9 | /** 10 | * MSSQLServer 数据库实现分页方言 11 | * 12 | * @author poplar.yfyang 13 | * @version 1.0 2010-10-10 下午12:31 14 | * @since JDK 1.5 15 | */ 16 | public class SQLServerDialect implements Dialect { 17 | 18 | static int getAfterSelectInsertPoint(String sql) { 19 | int selectIndex = sql.toLowerCase().indexOf("select"); 20 | final int selectDistinctIndex = sql.toLowerCase().indexOf("select distinct"); 21 | return selectIndex + (selectDistinctIndex == selectIndex ? 15 : 6); 22 | } 23 | 24 | public boolean supportsLimit() { 25 | return true; 26 | } 27 | 28 | public String getLimitString(String sql, int offset, int limit) { 29 | return getLimit(sql, offset, limit); 30 | } 31 | 32 | /** 33 | * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. 34 | *
35 |      * 如mysql
36 |      * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回
37 |      * select * from user limit :offset,:limit
38 |      * 
39 | * 40 | * @param sql 实际SQL语句 41 | * @param offset 分页开始纪录条数 42 | * @param limit 分页每页显示纪录条数 43 | * @return 包含占位符的分页sql 44 | */ 45 | public String getLimit(String sql, int offset, int limit) { 46 | if (offset > 0) { 47 | throw new UnsupportedOperationException("sql server has no offset"); 48 | } 49 | return new StringBuffer(sql.length() + 8) 50 | .append(sql) 51 | .insert(getAfterSelectInsertPoint(sql), " top " + limit) 52 | .toString(); 53 | } 54 | 55 | @Override 56 | public String getCountString(String querySqlString) { 57 | String sql = SQLServer2005Dialect.getNonOrderByPart(querySqlString); 58 | return "select count(1) from (" + sql + ") as tmp_count"; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Mybatis Pagination 2 | support Mysql、MSSQL、Oracle、MSSQL2005、Postgre SQL、DB2. 3 | 4 | ## Basic Usage 5 | in the Mybatis config, add the plugin. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | * `dbms`,database type. MYSQL\MSSQL\ORACLE\MSSQL2005\DB2 15 | * `sqlRegex` the mapper method/ sql mapper xml's id, regex string. 16 | * example `.*findAll.*` contain `findAll` query sql 17 | 18 | ### Sql Mapper config 19 | 20 | 26 | 27 | # Spring usage 28 | 29 | @see [config](https://github.com/yfyang/mybatis-pagination/blob/master/src/test/resources/spring/test-context.xml) And [TestCase](https://github.com/yfyang/mybatis-pagination/tree/master/src/test/java/org/mybatis/pagination/service) 30 | 31 | # Maven Usage 32 | 33 | 1. add repositories into you project `pom.xml` 34 | 35 | 36 | 37 | yfyang-mvn-repo 38 | https://raw.github.com/yfyang/mybatis-pagination/mvn-repo/ 39 | 40 | true 41 | always 42 | 43 | 44 | 45 | 46 | 2. add propertie into `pom.xml`:properties 47 | 48 | 49 | 0.0.3 50 | 51 | 52 | 3. add dependency into `pom.xml` 53 | 54 | 55 | org.mybatis 56 | mybatis-pagination 57 | ${org.mybatis.pagination.version} 58 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dialect/DialectClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.dialect; 6 | 7 | import java.io.Serializable; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | import org.mybatis.pagination.dialect.db.DB2Dialect; 12 | import org.mybatis.pagination.dialect.db.H2Dialect; 13 | import org.mybatis.pagination.dialect.db.HSQLDialect; 14 | import org.mybatis.pagination.dialect.db.MySQLDialect; 15 | import org.mybatis.pagination.dialect.db.OracleDialect; 16 | import org.mybatis.pagination.dialect.db.PostgreSQLDialect; 17 | import org.mybatis.pagination.dialect.db.SQLServer2005Dialect; 18 | import org.mybatis.pagination.dialect.db.SQLServerDialect; 19 | import org.mybatis.pagination.dialect.db.SybaseDialect; 20 | 21 | 22 | /** 23 | *

24 | * 数据库分页方言获取类. 25 | *

26 | * 27 | * @author poplar.yfyang 28 | * @version 1.0 2011-11-18 下午2:54 29 | * @since JDK 1.5 30 | */ 31 | public class DialectClient implements Serializable { 32 | private static final long serialVersionUID = 8107330250767760951L; 33 | private static final Map DBMS_DIALECT = new HashMap(); 34 | 35 | /** 36 | * 根据数据库名称获取数据库分页查询的方言实现。 37 | * 38 | * @param dbms 数据库名称 39 | * @return 数据库分页方言实现 40 | */ 41 | public static Dialect getDbmsDialect(DBMS dbms) { 42 | if (DBMS_DIALECT.containsKey(dbms)) { 43 | return DBMS_DIALECT.get(dbms); 44 | } 45 | Dialect dialect = createDbmsDialect(dbms); 46 | DBMS_DIALECT.put(dbms, dialect); 47 | return dialect; 48 | } 49 | 50 | /** 51 | * 插入自定义方言的实例 52 | * 53 | * @param exDialect 方言实现 54 | */ 55 | public static void putEx(Dialect exDialect) { 56 | DBMS_DIALECT.put(DBMS.EX, exDialect); 57 | } 58 | 59 | /** 60 | * 创建数据库方言 61 | * 62 | * @param dbms 数据库 63 | * @return 数据库 64 | */ 65 | private static Dialect createDbmsDialect(DBMS dbms) { 66 | switch (dbms) { 67 | case MYSQL: 68 | return new MySQLDialect(); 69 | case ORACLE: 70 | return new OracleDialect(); 71 | case DB2: 72 | return new DB2Dialect(); 73 | case POSTGRE: 74 | return new PostgreSQLDialect(); 75 | case SQLSERVER: 76 | return new SQLServerDialect(); 77 | case SQLSERVER2005: 78 | return new SQLServer2005Dialect(); 79 | case SYBASE: 80 | return new SybaseDialect(); 81 | case H2: 82 | return new H2Dialect(); 83 | case HSQL: 84 | return new HSQLDialect(); 85 | default: 86 | throw new UnsupportedOperationException("Empty dbms dialect"); 87 | } 88 | } 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/test/java/org/mybatis/pagination/mapper/ResourcesMapper.java: -------------------------------------------------------------------------------- 1 | package org.mybatis.pagination.mapper; 2 | 3 | import org.apache.ibatis.annotations.Param; 4 | import org.mybatis.pagination.domain.Resources; 5 | import org.mybatis.pagination.domain.ResourcesCriteria; 6 | import org.mybatis.pagination.dto.PageMyBatis; 7 | import org.mybatis.pagination.dto.datatables.PagingCriteria; 8 | import org.mybatis.pagination.extra.MyBatisRepository; 9 | 10 | import java.util.List; 11 | 12 | @MyBatisRepository 13 | public interface ResourcesMapper { 14 | /** 15 | * 根据指定的条件删除系统资源的数据库记录,auth_resources 16 | * 17 | * @param example 动态SQL条件实例 18 | */ 19 | int deleteByExample(ResourcesCriteria example); 20 | 21 | /** 22 | * 根据主键删除系统资源的数据库记录,auth_resources 23 | * 24 | * @param id 主键唯一标志 25 | */ 26 | int deleteByPrimaryKey(String id); 27 | 28 | /** 29 | * 新写入系统资源的数据库记录,auth_resources 30 | * 31 | * @param record 系统资源 32 | */ 33 | int insert(Resources record); 34 | 35 | /** 36 | * 动态字段,写入系统资源的数据库记录,auth_resources 37 | * 38 | * @param record 系统资源 39 | */ 40 | int insertSelective(Resources record); 41 | 42 | /** 43 | * 根据指定的条件查询符合条件的系统资源的数据库记录,auth_resources 44 | * 45 | * @param example 动态SQL条件实例 46 | */ 47 | List selectByExample(ResourcesCriteria example); 48 | 49 | /** 50 | * 根据指定主键获取系统资源的数据库记录,auth_resources 51 | * 52 | * @param id 主键唯一标志 53 | */ 54 | Resources selectByPrimaryKey(String id); 55 | 56 | /** 57 | * 动态根据指定的条件来更新符合条件的系统资源的数据库记录,auth_resources 58 | * 59 | * @param record 系统资源 60 | * @param example 动态SQL条件实例 61 | */ 62 | int updateByExampleSelective(@Param("record") Resources record, @Param("example") ResourcesCriteria example); 63 | 64 | /** 65 | * 根据指定的条件来更新符合条件的系统资源的数据库记录,auth_resources 66 | * 67 | * @param record 系统资源 68 | * @param example 动态SQL条件实例 69 | */ 70 | int updateByExample(@Param("record") Resources record, @Param("example") ResourcesCriteria example); 71 | 72 | /** 73 | * 动态字段,根据主键来更新符合条件的系统资源的数据库记录,auth_resources 74 | * 75 | * @param record 系统资源 76 | */ 77 | int updateByPrimaryKeySelective(Resources record); 78 | 79 | /** 80 | * 根据主键来更新符合条件的系统资源的数据库记录,auth_resources 81 | * 82 | * @param record 系统资源 83 | */ 84 | int updateByPrimaryKey(Resources record); 85 | 86 | PageMyBatis selectByPage(PagingCriteria pagingCriteria); 87 | PageMyBatis selectByPageOrder(PagingCriteria pagingCriteria); 88 | PageMyBatis selectByPageOrderAndWhere(PagingCriteria pagingCriteria,@Param("name") String name); 89 | } -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dialect/db/OracleDialect.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.dialect.db; 6 | 7 | import org.mybatis.pagination.dialect.Dialect; 8 | 9 | /** 10 | * Oracle的方言实现 11 | * 12 | * @author poplar.yfyang 13 | * @version 1.0 2010-10-10 下午12:31 14 | * @since JDK 1.5 15 | */ 16 | public class OracleDialect implements Dialect { 17 | @Override 18 | public boolean supportsLimit() { 19 | return true; 20 | } 21 | 22 | @Override 23 | public String getLimitString(String sql, int offset, int limit) { 24 | return getLimitString(sql, offset, Integer.toString(offset), Integer.toString(limit)); 25 | } 26 | 27 | /** 28 | * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. 29 | *
30 |      * 如mysql
31 |      * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回
32 |      * select * from user limit :offset,:limit
33 |      * 
34 | * 35 | * @param sql 实际SQL语句 36 | * @param offset 分页开始纪录条数 37 | * @param offsetPlaceholder 分页开始纪录条数-占位符号 38 | * @param limitPlaceholder 分页纪录条数占位符号 39 | * @return 包含占位符的分页sql 40 | */ 41 | public String getLimitString(String sql, int offset, String offsetPlaceholder, String limitPlaceholder) { 42 | sql = sql.trim(); 43 | boolean isForUpdate = false; 44 | if (sql.toLowerCase().endsWith(" for update")) { 45 | sql = sql.substring(0, sql.length() - 11); 46 | isForUpdate = true; 47 | } 48 | StringBuilder pagingSelect = new StringBuilder(sql.length() + 100); 49 | if (offset >= 0) { 50 | pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( "); 51 | } else { 52 | pagingSelect.append("select * from ( "); 53 | } 54 | pagingSelect.append(sql); 55 | if (offset >= 0) { 56 | String endString = offsetPlaceholder + "+" + limitPlaceholder; 57 | pagingSelect.append(" ) row_ ) where rownum_ <= ") 58 | .append(endString).append(" and rownum_ > ").append(offsetPlaceholder); 59 | } else { 60 | pagingSelect.append(" ) where rownum <= ").append(limitPlaceholder); 61 | } 62 | 63 | if (isForUpdate) { 64 | pagingSelect.append(" for update"); 65 | } 66 | 67 | return pagingSelect.toString(); 68 | } 69 | 70 | @Override 71 | public String getCountString(String querySqlString) { 72 | String sql = SQLServer2005Dialect.getNonOrderByPart(querySqlString); 73 | 74 | return "select count(1) from (" + sql + ") tmp_count"; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dto/PageMyBatis.java: -------------------------------------------------------------------------------- 1 | package org.mybatis.pagination.dto; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | import java.util.List; 6 | 7 | import com.google.common.base.Objects; 8 | import com.google.common.collect.Lists; 9 | import org.mybatis.pagination.dto.datatables.PagingCriteria; 10 | import org.mybatis.pagination.mvc.DataTablesResultSet; 11 | 12 | /** 13 | *

14 | * PageMyBatis. 15 | *

16 | * 17 | * @author mumu @yfyang 18 | * @version 1.0 2013-08-03 9:31 PM 19 | * @since JDK 1.5 20 | */ 21 | public class PageMyBatis extends ArrayList { 22 | private static final long serialVersionUID = -3472924628671922516L; 23 | /** 24 | * data connection. 25 | */ 26 | private final List content = Lists.newArrayList(); 27 | /** 28 | * pagination information 29 | */ 30 | private final PagingCriteria pageable; 31 | /** 32 | * count resultset. 33 | */ 34 | private final long total; 35 | 36 | /** 37 | * Instantiates a new Page my batis. 38 | * 39 | * @param content the content 40 | * @param pageable the pageable 41 | * @param total the total 42 | */ 43 | public PageMyBatis(Collection content, PagingCriteria pageable, long total) { 44 | super(content); 45 | 46 | this.content.addAll(content); 47 | this.total = total; 48 | this.pageable = pageable; 49 | } 50 | 51 | /** 52 | * Instantiates a new Page my batis. 53 | * 54 | * @param content the content 55 | */ 56 | public PageMyBatis(List content) { 57 | // fixed total is 0 throw NullPointException 58 | this(content, null, null == content ? 0 : content.size()); 59 | } 60 | 61 | /** 62 | * Gets total. 63 | * 64 | * @return the total 65 | */ 66 | public long getTotal() { 67 | return total; 68 | } 69 | 70 | /** 71 | * Warp page. 72 | * 73 | * @return the page 74 | */ 75 | public DataTablesResultSet warp() { 76 | return new DataTablesResultSet(pageable == null ? 0 : pageable.getPageNumber(), this); 77 | } 78 | 79 | @Override 80 | public String toString() { 81 | return Objects.toStringHelper(this) 82 | .add("content", content) 83 | .add("pageable", pageable) 84 | .add("total", total) 85 | .toString(); 86 | } 87 | 88 | @Override 89 | public boolean equals(Object o) { 90 | if (this == o) { 91 | return true; 92 | } 93 | if (o == null || getClass() != o.getClass()) { 94 | return false; 95 | } 96 | if (!super.equals(o)) { 97 | return false; 98 | } 99 | 100 | PageMyBatis that = (PageMyBatis) o; 101 | 102 | return total == that.total && !(content != null ? !content.equals(that.content) : that.content != null) && !(pageable != null ? !pageable.equals(that.pageable) : that.pageable != null); 103 | 104 | } 105 | 106 | @Override 107 | public int hashCode() { 108 | int result = super.hashCode(); 109 | result = 31 * result + (content != null ? content.hashCode() : 0); 110 | result = 31 * result + (pageable != null ? pageable.hashCode() : 0); 111 | result = 31 * result + (int) (total ^ (total >>> 32)); 112 | return result; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dialect/db/DB2Dialect.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.dialect.db; 6 | 7 | 8 | import org.mybatis.pagination.dialect.Dialect; 9 | 10 | /** 11 | * DB2的分页数据库方言实现 12 | * 13 | * @author poplar.yfyang 14 | * @version 1.0 2010-10-10 下午12:31 15 | * @since JDK 1.5 16 | */ 17 | public class DB2Dialect implements Dialect { 18 | private static String getRowNumber(String sql) { 19 | StringBuilder rownumber = new StringBuilder(50) 20 | .append("rownumber() over("); 21 | 22 | int orderByIndex = sql.toLowerCase().indexOf("order by"); 23 | 24 | if (orderByIndex > 0 && !hasDistinct(sql)) { 25 | rownumber.append(sql.substring(orderByIndex)); 26 | } 27 | 28 | rownumber.append(") as rownumber_,"); 29 | 30 | return rownumber.toString(); 31 | } 32 | 33 | private static boolean hasDistinct(String sql) { 34 | return sql.toLowerCase().contains("select distinct"); 35 | } 36 | 37 | @Override 38 | public boolean supportsLimit() { 39 | return true; 40 | } 41 | 42 | @Override 43 | public String getLimitString(String sql, int offset, int limit) { 44 | return getLimitString(sql, offset, Integer.toString(offset), Integer.toString(limit)); 45 | } 46 | 47 | /** 48 | * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. 49 | *
50 |      * 如mysql
51 |      * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回
52 |      * select * from user limit :offset,:limit
53 |      * 
54 | * 55 | * @param sql 实际SQL语句 56 | * @param offset 分页开始纪录条数 57 | * @param offsetPlaceholder 分页开始纪录条数-占位符号 58 | * @param limitPlaceholder 分页纪录条数占位符号 59 | * @return 包含占位符的分页sql 60 | */ 61 | public String getLimitString(String sql, int offset, String offsetPlaceholder, String limitPlaceholder) { 62 | int startOfSelect = sql.toLowerCase().indexOf("select"); 63 | 64 | StringBuilder pagingSelect = new StringBuilder(sql.length() + 100) 65 | .append(sql.substring(0, startOfSelect)) //add the comment 66 | .append("select * from ( select ") //nest the main query in an outer select 67 | .append(getRowNumber(sql)); //add the rownnumber bit into the outer query select list 68 | 69 | if (hasDistinct(sql)) { 70 | pagingSelect.append(" row_.* from ( ") //add another (inner) nested select 71 | .append(sql.substring(startOfSelect)) //add the main query 72 | .append(" ) as row_"); //close off the inner nested select 73 | } else { 74 | pagingSelect.append(sql.substring(startOfSelect + 6)); //add the main query 75 | } 76 | 77 | pagingSelect.append(" ) as temp_ where rownumber_ "); 78 | 79 | //add the restriction to the outer select 80 | if (offset > 0) { 81 | // int end = offset + limit; 82 | String endString = offsetPlaceholder + "+" + limitPlaceholder; 83 | pagingSelect.append("between ").append(offsetPlaceholder) 84 | .append("+1 and ").append(endString); 85 | } else { 86 | pagingSelect.append("<= ").append(limitPlaceholder); 87 | } 88 | 89 | return pagingSelect.toString(); 90 | } 91 | 92 | @Override 93 | public String getCountString(String querySqlString) { 94 | String sql = SQLServer2005Dialect.getNonOrderByPart(querySqlString); 95 | return "select count(1) from (" + sql + ") as tmp_count"; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/test/resources/spring/test-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 30 | 31 | 32 | 33 | 35 | 36 | 37 | 38 | 39 | 40 | ${database_dialect} 41 | .*ByPage.* 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dialect/db/SQLServer2005Dialect.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.dialect.db; 6 | 7 | import io.github.sparta.helpers.sql.SqlRemoveHelper; 8 | import org.mybatis.pagination.dialect.Dialect; 9 | import org.mybatis.pagination.helpers.CountHelper; 10 | import org.mybatis.pagination.helpers.StringHelper; 11 | 12 | /** 13 | * Sql 2005的方言实现 14 | * 15 | * @author poplar.yfyang 16 | * @version 1.0 2010-10-10 下午12:31 17 | * @since JDK 1.5 18 | */ 19 | public class SQLServer2005Dialect implements Dialect { 20 | 21 | static String getOrderByPart(String sql) { 22 | String loweredString = sql.toLowerCase(); 23 | int orderByIndex = loweredString.indexOf("order by"); 24 | if (orderByIndex != -1) { 25 | // if we find a new "order by" then we need to ignore 26 | // the previous one since it was probably used for a subquery 27 | return sql.substring(orderByIndex); 28 | } else { 29 | return ""; 30 | } 31 | } 32 | 33 | /** 34 | * exclude in 'order by ' by sql 35 | * 36 | * @param sql sql 37 | * @return count sql. 38 | */ 39 | public static String getNonOrderByPart(String sql) { 40 | return SqlRemoveHelper.removeOrders(sql); 41 | } 42 | 43 | @Override 44 | public boolean supportsLimit() { 45 | return true; 46 | } 47 | 48 | @Override 49 | public String getLimitString(String sql, int offset, int limit) { 50 | return getLimitString(sql, offset, 51 | limit, Integer.toString(limit)); 52 | } 53 | 54 | /** 55 | * Add a LIMIT clause to the given SQL SELECT 56 | *

57 | * The LIMIT SQL will look like: 58 | *

59 | * WITH query AS 60 | * (SELECT TOP 100 percent ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __row_number__, * from table_name) 61 | * SELECT * 62 | * FROM query 63 | * WHERE __row_number__ BETWEEN :offset and :lastRows 64 | * ORDER BY __row_number__ 65 | * 66 | * @param querySqlString The SQL statement to base the limit query off of. 67 | * @param offset Offset of the first row to be returned by the query (zero-based) 68 | * @param limit Maximum number of rows to be returned by the query 69 | * @param limitPlaceholder limitPlaceholder 70 | * @return A new SQL statement with the LIMIT clause applied. 71 | */ 72 | private String getLimitString(String querySqlString, int offset, int limit, String limitPlaceholder) { 73 | StringBuilder pagingBuilder = new StringBuilder(); 74 | String orderby = getOrderByPart(querySqlString); 75 | String distinctStr = ""; 76 | 77 | String loweredString = querySqlString.toLowerCase(); 78 | String sqlPartString = querySqlString; 79 | if (loweredString.trim().startsWith("select")) { 80 | int index = 6; 81 | if (loweredString.startsWith("select distinct")) { 82 | distinctStr = "DISTINCT "; 83 | index = 15; 84 | } 85 | sqlPartString = sqlPartString.substring(index); 86 | } 87 | pagingBuilder.append(sqlPartString); 88 | 89 | // if no ORDER BY is specified use fake ORDER BY field to avoid errors 90 | if (StringHelper.isEmpty(orderby)) { 91 | orderby = "ORDER BY CURRENT_TIMESTAMP"; 92 | } 93 | 94 | StringBuilder result = new StringBuilder(); 95 | result.append("WITH query AS (SELECT ") 96 | .append(distinctStr) 97 | .append("TOP 100 PERCENT ") 98 | .append(" ROW_NUMBER() OVER (") 99 | .append(orderby) 100 | .append(") as __row_number__, ") 101 | .append(pagingBuilder) 102 | .append(") SELECT * FROM query WHERE __row_number__ BETWEEN ") 103 | .append(offset + 1).append(" AND ").append(offset + limit) 104 | .append(" ORDER BY __row_number__"); 105 | 106 | return result.toString(); 107 | } 108 | 109 | @Override 110 | public String getCountString(String querySqlString) { 111 | String sql = getNonOrderByPart(querySqlString); 112 | 113 | return "select count(1) from (" + sql + ") as tmp_count"; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/test/java/org/mybatis/pagination/service/MapperTest.java: -------------------------------------------------------------------------------- 1 | package org.mybatis.pagination.service; 2 | 3 | import java.util.List; 4 | import javax.annotation.Resource; 5 | 6 | import com.google.common.collect.Lists; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.mybatis.pagination.domain.Resources; 10 | import org.mybatis.pagination.dto.PageMyBatis; 11 | import org.mybatis.pagination.dto.datatables.PagingCriteria; 12 | import org.mybatis.pagination.dto.datatables.SearchField; 13 | import org.mybatis.pagination.dto.datatables.SortDirection; 14 | import org.mybatis.pagination.dto.datatables.SortField; 15 | import org.mybatis.pagination.mapper.ResourcesMapper; 16 | import org.springframework.test.context.ContextConfiguration; 17 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 18 | 19 | /** 20 | *

21 | * . 22 | *

23 | * 24 | * @author mumu@yfyang 25 | * @version 1.0 2013-09-09 2:15 PM 26 | * @since JDK 1.5 27 | */ 28 | @RunWith(SpringJUnit4ClassRunner.class) 29 | @ContextConfiguration("classpath*:spring/test-context.xml") 30 | public class MapperTest { 31 | 32 | @Resource 33 | private ResourcesMapper resourcesMapper; 34 | 35 | // @Before 36 | // //使用该注释会使用事务,而且在测试完成之后会回滚事务,也就是说在该方法中做出的一切操作都不会对数据库中的数据产生任何影响 37 | // @Rollback(false) //这里设置为false,就让事务不回滚 38 | // public void setUp() throws Exception { 39 | // Resources resources; 40 | // for (int i = 0; i < 1000; i++) { 41 | // resources = new Resources(); 42 | // resources.setId(UUID.randomUUID().toString()); 43 | // resources.setName("测试数据" + i); 44 | // resources.setPath("test/pageh/" + i); 45 | // resourcesMapper.insertSelective(resources); 46 | // } 47 | // 48 | // } 49 | 50 | @Test 51 | public void testPagaination() throws Exception { 52 | 53 | PagingCriteria baseCriteria = PagingCriteria.createCriteria(0, 15, 15); 54 | PageMyBatis pageMyBatis = resourcesMapper.selectByPage(baseCriteria); 55 | for (Resources pageMyBati : pageMyBatis) { 56 | System.out.println(pageMyBati); 57 | } 58 | } 59 | 60 | @Test 61 | public void testPagainationSqlContainOrder() throws Exception { 62 | PagingCriteria baseCriteria = PagingCriteria.createCriteria(0, 15, 15); 63 | PageMyBatis pageMyBatis = resourcesMapper.selectByPageOrder(baseCriteria); 64 | for (Resources pageMyBati : pageMyBatis) { 65 | System.out.println(pageMyBati); 66 | } 67 | 68 | } 69 | 70 | @Test 71 | public void testPagainationAndWrap() throws Exception { 72 | PagingCriteria baseCriteria = PagingCriteria.createCriteria(0, 15, 15); 73 | PageMyBatis pageMyBatis = resourcesMapper.selectByPage(baseCriteria); 74 | System.out.println("pageMyBatis.warp() = " + pageMyBatis.warp()); 75 | } 76 | 77 | @Test 78 | public void testPagainationAndOrder() throws Exception { 79 | 80 | List sortFields = Lists.newArrayList(); 81 | sortFields.add(new SortField("name", SortDirection.DESC)); 82 | sortFields.add(new SortField("path", SortDirection.ASC)); 83 | 84 | PagingCriteria baseCriteria = PagingCriteria.createCriteriaWithSort(20, 15, 15, sortFields); 85 | PageMyBatis pageMyBatis = resourcesMapper.selectByPage(baseCriteria); 86 | for (Resources pageMyBati : pageMyBatis) { 87 | System.out.println(pageMyBati); 88 | } 89 | } 90 | 91 | @Test 92 | public void testPagainationAndSearch() throws Exception { 93 | List searchFields = Lists.newArrayList(); 94 | searchFields.add(new SearchField("name", false, false, "11")); 95 | 96 | PagingCriteria baseCriteria = PagingCriteria.createCriteriaWithSearch(0, 15, 15, searchFields); 97 | PageMyBatis pageMyBatis = resourcesMapper.selectByPage(baseCriteria); 98 | for (Resources pageMyBati : pageMyBatis) { 99 | System.out.println(pageMyBati); 100 | } 101 | } 102 | 103 | @Test 104 | public void testPagainationAndOrderSearch() throws Exception { 105 | List searchFields = Lists.newArrayList(); 106 | searchFields.add(new SearchField("name", false, false, "11")); 107 | 108 | PagingCriteria baseCriteria = PagingCriteria.createCriteriaWithSearch(0, 15, 15, searchFields); 109 | PageMyBatis pageMyBatis = resourcesMapper.selectByPageOrder(baseCriteria); 110 | for (Resources pageMyBati : pageMyBatis) { 111 | System.out.println(pageMyBati); 112 | } 113 | } 114 | 115 | @Test 116 | public void testPaginationMoreWhere() throws Exception { 117 | List searchFields = Lists.newArrayList(); 118 | searchFields.add(new SearchField("name", false, false, "11")); 119 | 120 | PagingCriteria baseCriteria = PagingCriteria.createCriteriaWithSearch(0, 15, 15, searchFields); 121 | PageMyBatis pageMyBatis = resourcesMapper.selectByPageOrderAndWhere(baseCriteria,"aa"); 122 | for (Resources pageMyBati : pageMyBatis) { 123 | System.out.println(pageMyBati); 124 | } 125 | 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/helpers/StringHelper.java: -------------------------------------------------------------------------------- 1 | package org.mybatis.pagination.helpers; 2 | 3 | /** 4 | *

5 | * Help class by String. 6 | *

7 | * 8 | * @author mumu@yfyang 9 | * @version 1.0 2013-09-09 11:26 AM 10 | * @since JDK 1.5 11 | */ 12 | public final class StringHelper { 13 | 14 | 15 | /** The empty String {@code ""}. */ 16 | public static final String EMPTY = ""; 17 | /** The dot String {@code ","}. */ 18 | public static final String DOT_CHAR = ","; 19 | /** The blank String {@code " "}. */ 20 | public static final String BLANK_CHAR = " "; 21 | /** The equal sign String {@code "="} */ 22 | public static final String EQUAL_SIGN_CHAR = "="; 23 | /** 24 | * The like String {@code "like"} 25 | */ 26 | public static final String LIKE_CHAR = " like "; 27 | private static final String INJECTION_SQL = ".*([';]+|(--)+).*"; 28 | private static String LIKE_FORMATE = "'%%s%'"; 29 | 30 | /** 31 | *

Checks if a CharSequence is not empty ("") and not null.

32 | *

33 | *

 34 |      * StringUtils.isNotEmpty(null)      = false
 35 |      * StringUtils.isNotEmpty("")        = false
 36 |      * StringUtils.isNotEmpty(" ")       = true
 37 |      * StringUtils.isNotEmpty("bob")     = true
 38 |      * StringUtils.isNotEmpty("  bob  ") = true
 39 |      * 
40 | * 41 | * @param cs the CharSequence to check, may be null 42 | * @return {@code true} if the CharSequence is not empty and not null 43 | * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence) 44 | */ 45 | public static boolean isNotEmpty(CharSequence cs) { 46 | return !isEmpty(cs); 47 | } 48 | 49 | /** 50 | *

Checks if a CharSequence is empty ("") or null.

51 | *

52 | *

 53 |      * StringUtils.isEmpty(null)      = true
 54 |      * StringUtils.isEmpty("")        = true
 55 |      * StringUtils.isEmpty(" ")       = false
 56 |      * StringUtils.isEmpty("bob")     = false
 57 |      * StringUtils.isEmpty("  bob  ") = false
 58 |      * 
59 | *

60 | *

NOTE: This method changed in Lang version 2.0. 61 | * It no longer trims the CharSequence. 62 | * That functionality is available in isBlank().

63 | * 64 | * @param cs the CharSequence to check, may be null 65 | * @return {@code true} if the CharSequence is empty or null 66 | * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence) 67 | */ 68 | public static boolean isEmpty(CharSequence cs) { 69 | return cs == null || cs.length() == 0; 70 | } 71 | 72 | /** 73 | *

Capitalizes a String changing the first letter to title case as 74 | * per {@link Character#toTitleCase(char)}. No other letters are changed.

75 | *

76 | *

For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#capitalize(String)}. 77 | * A {@code null} input String returns {@code null}.

78 | *

79 | *

 80 |      * StringUtils.capitalize(null)  = null
 81 |      * StringUtils.capitalize("")    = ""
 82 |      * StringUtils.capitalize("cat") = "Cat"
 83 |      * StringUtils.capitalize("cAt") = "CAt"
 84 |      * 
85 | * 86 | * @param str the String to capitalize, may be null 87 | * @return the capitalized String, {@code null} if null String input 88 | */ 89 | public static String capitalize(String str) { 90 | if (str == null || (str.length()) == 0) { 91 | return str; 92 | } 93 | return String.valueOf(Character.toTitleCase(str.charAt(0))) + str.substring(1); 94 | } 95 | 96 | /** 97 | *

Checks if a CharSequence is whitespace, empty ("") or null.

98 | *

99 | *

100 |      * StringUtils.isBlank(null)      = true
101 |      * StringUtils.isBlank("")        = true
102 |      * StringUtils.isBlank(" ")       = true
103 |      * StringUtils.isBlank("bob")     = false
104 |      * StringUtils.isBlank("  bob  ") = false
105 |      * 
106 | * 107 | * @param cs the CharSequence to check, may be null 108 | * @return {@code true} if the CharSequence is null, empty or whitespace 109 | * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence) 110 | */ 111 | public static boolean isBlank(CharSequence cs) { 112 | int strLen; 113 | if (cs == null || (strLen = cs.length()) == 0) { 114 | return true; 115 | } 116 | for (int i = 0; i < strLen; i++) { 117 | if (!Character.isWhitespace(cs.charAt(i))) { 118 | return false; 119 | } 120 | } 121 | return true; 122 | } 123 | 124 | /** 125 | * Transact sQL injection. 126 | * 127 | * @param sql the sql 128 | * @return the string 129 | */ 130 | public static String transactSQLInjection(String sql) { 131 | return sql.replaceAll(INJECTION_SQL, " "); 132 | } 133 | 134 | /** 135 | * Like value. 136 | * 137 | * @param value the value 138 | * @return the string 139 | */ 140 | public static String likeValue(String value) { 141 | return String.format(LIKE_FORMATE, transactSQLInjection(value)); 142 | } 143 | 144 | } 145 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/PagingParametersFinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination; 6 | 7 | import com.google.common.collect.Maps; 8 | import org.apache.commons.beanutils.BeanMap; 9 | import org.mybatis.pagination.dto.datatables.PagingCriteria; 10 | import org.mybatis.pagination.helpers.StringHelper; 11 | 12 | import java.lang.reflect.Array; 13 | import java.util.Collection; 14 | import java.util.Map; 15 | 16 | /** 17 | *

18 | * Paging PaginationCriteria finds. 19 | *

20 | * 21 | * @author poplar.yfyang 22 | * @version 1.0 2012-12-09 7:22 PM 23 | * @since JDK 1.5 24 | */ 25 | public enum PagingParametersFinder { 26 | 27 | instance; 28 | 29 | /** 30 | * The search parameters by use of interim storage of results. 31 | */ 32 | private final Map search_map = Maps.newHashMap(); 33 | 34 | /** 35 | * private constructor 36 | */ 37 | private PagingParametersFinder() { 38 | } 39 | 40 | 41 | /** 42 | * from the formulation of the objects found in the paging parameters object. 43 | * 44 | * @param object object. 45 | * @return paging parameters. 46 | */ 47 | public PagingCriteria findCriteria(Object object) { 48 | if (object == null) { 49 | return null; 50 | } 51 | try { 52 | return findCriteriaFromObject(object); 53 | } finally { 54 | //cleanup query the value of the temporary Map. 55 | search_map.clear(); 56 | } 57 | } 58 | 59 | /** 60 | * In the object to find whether contains PaginationCriteria objects. 61 | * 62 | * @param object parameter object. 63 | * @return PaginationCriteria 64 | */ 65 | private PagingCriteria findCriteriaFromObject(Object object) { 66 | 67 | //如果已经寻找过这个对象,现在再来这里肯定是没找到。就直接返回NULL 68 | if (search_map.containsKey(object)) { 69 | return null; 70 | } 71 | //object class 72 | Class obj_class = object.getClass(); 73 | PagingCriteria pc; 74 | //primitive 75 | if (isPrimitiveType(obj_class)) { 76 | pc = null; 77 | } else if (object instanceof PagingCriteria) { 78 | pc = (PagingCriteria) object; 79 | } else if (object instanceof Map) { 80 | pc = findCriteriaFromMap((Map) object); 81 | } else if (object instanceof Collection) { 82 | pc = findCriteriaFromCollection((Collection) object); 83 | } else if (obj_class.isArray()) { 84 | pc = findCriteriaFromArray(object); 85 | } else { 86 | BeanMap map = new BeanMap(object); 87 | return findCriteriaFromMap(map); 88 | } 89 | 90 | 91 | search_map.put(object, StringHelper.EMPTY); 92 | return pc; 93 | } 94 | 95 | /** 96 | * In the array to find whether it contains the PaginationCriteria object. 97 | * 98 | * @param array the array. 99 | * @return PageQuery 100 | */ 101 | private PagingCriteria findCriteriaFromArray(Object array) { 102 | if (search_map.containsKey(array)) { 103 | return null; 104 | } 105 | 106 | Object object; 107 | PagingCriteria pc; 108 | for (int i = 0; i < Array.getLength(array); i++) { 109 | object = Array.get(array, i); 110 | pc = findCriteriaFromObject(object); 111 | if (pc != null) { 112 | search_map.put(array, StringHelper.EMPTY); 113 | return pc; 114 | } 115 | } 116 | search_map.put(array, StringHelper.EMPTY); 117 | return null; 118 | } 119 | 120 | /** 121 | * In the Collection to find whether contains PaginationCriteria objects. 122 | * 123 | * @param collection parameter collection. 124 | * @return PageQuery 125 | */ 126 | private PagingCriteria findCriteriaFromCollection(Collection collection) { 127 | if (search_map.containsKey(collection)) { 128 | return null; 129 | } 130 | PagingCriteria pc; 131 | 132 | for (Object e : collection) { 133 | pc = findCriteriaFromObject(e); 134 | if (pc != null) { 135 | search_map.put(collection, StringHelper.EMPTY); 136 | return pc; 137 | } 138 | } 139 | 140 | search_map.put(collection, StringHelper.EMPTY); 141 | return null; 142 | } 143 | 144 | /** 145 | * In the Map to find whether contains PaginationCriteria objects. 146 | * 147 | * @param map parameter map. 148 | * @return PaginationCriteria 149 | */ 150 | private PagingCriteria findCriteriaFromMap(Map map) { 151 | if (search_map.containsKey(map)) { 152 | return null; 153 | } 154 | 155 | PagingCriteria pc; 156 | for (Object value : map.values()) { 157 | pc = findCriteriaFromObject(value); 158 | if (pc != null) { 159 | search_map.put(map, StringHelper.EMPTY); 160 | return pc; 161 | } 162 | } 163 | 164 | search_map.put(map, StringHelper.EMPTY); 165 | return null; 166 | } 167 | 168 | 169 | 170 | /** 171 | * 返回指定类型所对应的primitive类型。包含String类 172 | *

173 | * fixed:paramter string type. 174 | * 175 | * @param clazz 要检查的类型 176 | * @return 如果指定类型为null或不是primitive类型的包装类,则返回false,否则返回true。 177 | */ 178 | public static boolean isPrimitiveType(Class clazz) { 179 | return clazz != null && (clazz.isPrimitive() || clazz.equals(Long.class) || clazz.equals(Integer.class) 180 | || clazz.equals(Short.class) || clazz.equals(Byte.class) || clazz.equals(Double.class) 181 | || clazz.equals(Float.class) || clazz.equals(Boolean.class) || clazz.equals(Character.class) || clazz.equals(String.class)); 182 | 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/PaginationExecutor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination; 6 | 7 | import java.sql.SQLException; 8 | import java.util.List; 9 | 10 | import org.apache.ibatis.cache.Cache; 11 | import org.apache.ibatis.cache.CacheKey; 12 | import org.apache.ibatis.executor.BatchResult; 13 | import org.apache.ibatis.executor.CachingExecutor; 14 | import org.apache.ibatis.executor.Executor; 15 | import org.apache.ibatis.logging.Log; 16 | import org.apache.ibatis.logging.LogFactory; 17 | import org.apache.ibatis.mapping.BoundSql; 18 | import org.apache.ibatis.mapping.MappedStatement; 19 | import org.apache.ibatis.reflection.MetaObject; 20 | import org.apache.ibatis.session.ResultHandler; 21 | import org.apache.ibatis.session.RowBounds; 22 | import org.apache.ibatis.transaction.Transaction; 23 | import org.mybatis.pagination.dto.PageMyBatis; 24 | 25 | 26 | /** 27 | * Paging executor. 28 | * Dependence of mybatis agent. 29 | * 30 | * @author poplar.yfyang 31 | * @author htlu 32 | * @version 1.0 2012-09-09 7:22 PM 33 | * @since JDK 1.5 34 | */ 35 | public class PaginationExecutor implements Executor { 36 | 37 | /** logging */ 38 | private static final Log LOG = LogFactory.getLog(PaginationExecutor.class); 39 | /** mybatis executor interface */ 40 | private final Executor executor; 41 | 42 | /** 43 | * Paging Constructor. 44 | * 45 | * @param executor Trim executor. 46 | */ 47 | public PaginationExecutor(Executor executor) { 48 | this.executor = executor; 49 | } 50 | 51 | @Override 52 | public int update(MappedStatement ms, Object parameter) throws SQLException { 53 | 54 | return executor.update(ms, parameter); 55 | } 56 | 57 | @Override 58 | public List query(MappedStatement ms, Object parameter, 59 | RowBounds rowBounds, ResultHandler resultHandler, 60 | CacheKey cacheKey, BoundSql boundSql) throws SQLException { 61 | 62 | final List rows = executor.query(ms, parameter, rowBounds, resultHandler); 63 | int total = PaginationInterceptor.getPaginationTotal(); 64 | try { 65 | if (total != 0) { 66 | final PageMyBatis result = new PageMyBatis(rows, PaginationInterceptor.getPageRequest(), total); 67 | doCache(ms, result, parameter, rowBounds); 68 | return result; 69 | } else { 70 | return new PageMyBatis(rows); 71 | } 72 | } finally { 73 | PaginationInterceptor.clean(); 74 | } 75 | } 76 | 77 | @Override 78 | public List query(MappedStatement ms, Object parameter, 79 | RowBounds rowBounds, ResultHandler resultHandler) 80 | throws SQLException { 81 | 82 | final List rows = executor.query(ms, parameter, rowBounds, resultHandler); 83 | int total = PaginationInterceptor.getPaginationTotal(); 84 | try { 85 | if (total != 0) { 86 | final PageMyBatis result = new PageMyBatis(rows, PaginationInterceptor.getPageRequest(), total); 87 | doCache(ms, result, parameter, rowBounds); 88 | return result; 89 | } else { 90 | return new PageMyBatis(rows); 91 | } 92 | } finally { 93 | PaginationInterceptor.clean(); 94 | } 95 | 96 | } 97 | 98 | /** 99 | * do mybatis cache with this executor. 100 | * 101 | * @param ms mapped statuement. 102 | * @param result database result. 103 | * @param parameter sql paramater. 104 | * @param rowBounds row bounds 105 | * @param paramter. 106 | */ 107 | private void doCache(MappedStatement ms, PageMyBatis result, Object parameter, RowBounds rowBounds) { 108 | // if the current of the executor is for CachingExecutor 109 | final Cache cache = ms.getCache(); 110 | // Determine whether the current query cache. 111 | if (executor.getClass().isAssignableFrom(CachingExecutor.class) && cache != null) { 112 | BoundSql boundSql = ms.getBoundSql(parameter); 113 | final CacheKey cacheKey = createCacheKey(ms, parameter, rowBounds, boundSql); 114 | if (LOG.isDebugEnabled()) { 115 | LOG.debug("cache executor the cache's kye is " + cacheKey); 116 | } 117 | cache.putObject(cacheKey, result); 118 | } 119 | } 120 | 121 | @Override 122 | public List flushStatements() throws SQLException { 123 | return executor.flushStatements(); 124 | } 125 | 126 | @Override 127 | public void commit(boolean required) throws SQLException { 128 | executor.commit(required); 129 | } 130 | 131 | @Override 132 | public void rollback(boolean required) throws SQLException { 133 | executor.rollback(required); 134 | } 135 | 136 | @Override 137 | public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, 138 | RowBounds rowBounds, BoundSql boundSql) { 139 | return executor.createCacheKey(ms, parameterObject, rowBounds, boundSql); 140 | } 141 | 142 | @Override 143 | public boolean isCached(MappedStatement ms, CacheKey key) { 144 | return executor.isCached(ms, key); 145 | } 146 | 147 | @Override 148 | public void clearLocalCache() { 149 | executor.clearLocalCache(); 150 | } 151 | 152 | @Override 153 | public void deferLoad(MappedStatement mappedStatement, MetaObject metaObject, 154 | String s, CacheKey cacheKey, Class aClass) { 155 | 156 | executor.deferLoad(mappedStatement, metaObject, s, cacheKey, aClass); 157 | } 158 | 159 | @Override 160 | public Transaction getTransaction() { 161 | return executor.getTransaction(); 162 | } 163 | 164 | @Override 165 | public void close(boolean forceRollback) { 166 | //clear 167 | PaginationInterceptor.clean(); 168 | executor.close(forceRollback); 169 | } 170 | 171 | @Override 172 | public boolean isClosed() { 173 | return executor.isClosed(); 174 | } 175 | 176 | } 177 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/helpers/CountHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.helpers; 6 | 7 | import java.sql.Connection; 8 | import java.sql.PreparedStatement; 9 | import java.sql.ResultSet; 10 | import java.sql.SQLException; 11 | import java.util.List; 12 | 13 | import org.apache.ibatis.executor.ErrorContext; 14 | import org.apache.ibatis.executor.ExecutorException; 15 | import org.apache.ibatis.logging.Log; 16 | import org.apache.ibatis.logging.LogFactory; 17 | import org.apache.ibatis.mapping.BoundSql; 18 | import org.apache.ibatis.mapping.MappedStatement; 19 | import org.apache.ibatis.mapping.ParameterMapping; 20 | import org.apache.ibatis.mapping.ParameterMode; 21 | import org.apache.ibatis.reflection.MetaObject; 22 | import org.apache.ibatis.reflection.property.PropertyTokenizer; 23 | import org.apache.ibatis.scripting.xmltags.ForEachSqlNode; 24 | import org.apache.ibatis.session.Configuration; 25 | import org.apache.ibatis.type.TypeHandler; 26 | import org.apache.ibatis.type.TypeHandlerRegistry; 27 | import org.mybatis.pagination.dialect.Dialect; 28 | 29 | /** 30 | *

31 | * . 32 | *

33 | * 34 | * @author poplar.yfyang 35 | * @version 1.0 2012-05-08 上午11:30 36 | * @since JDK 1.5 37 | */ 38 | public class CountHelper { 39 | 40 | public static final String SQL_ORDER = " order by "; 41 | public static final String OR_JOINER = " or "; 42 | public static final String OR_SQL_FORMAT = "%s or (%s) %s"; 43 | public static final String WHERE_SQL_FORMAT = "%s where (%s) %s"; 44 | public static final String SQL_FORMAT = "%s, %s"; 45 | public static final String ORDER_SQL_FORMAT = "%s order by %s"; 46 | /** logging */ 47 | private static final Log LOG = LogFactory.getLog(CountHelper.class); 48 | 49 | /** 50 | * 查询总纪录数 51 | * 52 | * @param sql SQL语句 53 | * @param connection 数据库连接 54 | * @param mappedStatement mapped 55 | * @param parameterObject 参数 56 | * @param boundSql boundSql 57 | * @param dialect database dialect 58 | * @return 总记录数 59 | * @throws java.sql.SQLException sql查询错误 60 | */ 61 | public static int getCount(final String sql, final Connection connection, 62 | final MappedStatement mappedStatement, final Object parameterObject, 63 | final BoundSql boundSql, Dialect dialect) throws SQLException { 64 | final String count_sql = dialect.getCountString(sql); 65 | if (LOG.isDebugEnabled()) { 66 | LOG.debug("the pagination generate count sql is [" + count_sql + "]"); 67 | } 68 | PreparedStatement countStmt = null; 69 | ResultSet rs = null; 70 | try { 71 | countStmt = connection.prepareStatement(count_sql); 72 | final BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), count_sql, 73 | boundSql.getParameterMappings(), parameterObject); 74 | CountHelper.setParameters(countStmt, mappedStatement, countBS, parameterObject); 75 | rs = countStmt.executeQuery(); 76 | int count = 0; 77 | if (rs.next()) { 78 | count = rs.getInt(1); 79 | } 80 | return count; 81 | } finally { 82 | if (rs != null) { 83 | rs.close(); 84 | } 85 | if (countStmt != null) { 86 | countStmt.close(); 87 | } 88 | } 89 | } 90 | 91 | /** 92 | * 对SQL参数(?)设值 93 | * 94 | * @param ps 表示预编译的 SQL 语句的对象。 95 | * @param mappedStatement MappedStatement 96 | * @param boundSql SQL 97 | * @param parameterObject 参数对象 98 | * @throws java.sql.SQLException 数据库异常 99 | */ 100 | @SuppressWarnings("unchecked") 101 | public static void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql, Object parameterObject) throws SQLException { 102 | ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId()); 103 | List parameterMappings = boundSql.getParameterMappings(); 104 | if (parameterMappings != null) { 105 | Configuration configuration = mappedStatement.getConfiguration(); 106 | TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry(); 107 | MetaObject metaObject = parameterObject == null ? null : 108 | configuration.newMetaObject(parameterObject); 109 | for (int i = 0; i < parameterMappings.size(); i++) { 110 | ParameterMapping parameterMapping = parameterMappings.get(i); 111 | if (parameterMapping.getMode() != ParameterMode.OUT) { 112 | Object value; 113 | String propertyName = parameterMapping.getProperty(); 114 | PropertyTokenizer prop = new PropertyTokenizer(propertyName); 115 | if (parameterObject == null) { 116 | value = null; 117 | } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { 118 | value = parameterObject; 119 | } else if (boundSql.hasAdditionalParameter(propertyName)) { 120 | value = boundSql.getAdditionalParameter(propertyName); 121 | } else if (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX) && boundSql.hasAdditionalParameter(prop.getName())) { 122 | value = boundSql.getAdditionalParameter(prop.getName()); 123 | if (value != null) { 124 | value = configuration.newMetaObject(value).getValue(propertyName.substring(prop.getName().length())); 125 | } 126 | } else { 127 | value = metaObject == null ? null : metaObject.getValue(propertyName); 128 | } 129 | TypeHandler typeHandler = parameterMapping.getTypeHandler(); 130 | if (typeHandler == null) { 131 | throw new ExecutorException("There was no TypeHandler found for parameter " + propertyName + " of statement " + mappedStatement.getId()); 132 | } 133 | typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType()); 134 | } 135 | } 136 | } 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /src/test/java/org/mybatis/pagination/domain/Resources.java: -------------------------------------------------------------------------------- 1 | package org.mybatis.pagination.domain; 2 | 3 | import com.google.common.base.Objects; 4 | 5 | import java.io.Serializable; 6 | 7 | public class Resources implements Serializable { 8 | /** 9 | * 主键,所属表字段为auth_resources.id 10 | */ 11 | private String id; 12 | 13 | /** 14 | * 资源名称,所属表字段为auth_resources.name 15 | */ 16 | private String name; 17 | 18 | /** 19 | * 资源类型,所属表字段为auth_resources.type 20 | */ 21 | private String type; 22 | 23 | /** 24 | * 资源地址,所属表字段为auth_resources.path 25 | */ 26 | private String path; 27 | 28 | /** 29 | * 资源请求,所属表字段为auth_resources.action 30 | */ 31 | private String action; 32 | 33 | /** 34 | * 资源控制,所属表字段为auth_resources.controller 35 | */ 36 | private String controller; 37 | 38 | /** 39 | * 状态,所属表字段为auth_resources.status 40 | */ 41 | private Boolean status; 42 | 43 | /** 44 | * 序列化ID,auth_resources 45 | */ 46 | private static final long serialVersionUID = 1L; 47 | 48 | /** 49 | * 获取 主键 字段:auth_resources.id 50 | * 51 | * @return auth_resources.id, 主键 52 | */ 53 | public String getId() { 54 | return id; 55 | } 56 | 57 | /** 58 | * 设置 主键 字段:auth_resources.id 59 | * 60 | * @param id auth_resources.id, 主键 61 | */ 62 | public void setId(String id) { 63 | this.id = id == null ? null : id.trim(); 64 | } 65 | 66 | /** 67 | * 获取 资源名称 字段:auth_resources.name 68 | * 69 | * @return auth_resources.name, 资源名称 70 | */ 71 | public String getName() { 72 | return name; 73 | } 74 | 75 | /** 76 | * 设置 资源名称 字段:auth_resources.name 77 | * 78 | * @param name auth_resources.name, 资源名称 79 | */ 80 | public void setName(String name) { 81 | this.name = name == null ? null : name.trim(); 82 | } 83 | 84 | /** 85 | * 获取 资源类型 字段:auth_resources.type 86 | * 87 | * @return auth_resources.type, 资源类型 88 | */ 89 | public String getType() { 90 | return type; 91 | } 92 | 93 | /** 94 | * 设置 资源类型 字段:auth_resources.type 95 | * 96 | * @param type auth_resources.type, 资源类型 97 | */ 98 | public void setType(String type) { 99 | this.type = type == null ? null : type.trim(); 100 | } 101 | 102 | /** 103 | * 获取 资源地址 字段:auth_resources.path 104 | * 105 | * @return auth_resources.path, 资源地址 106 | */ 107 | public String getPath() { 108 | return path; 109 | } 110 | 111 | /** 112 | * 设置 资源地址 字段:auth_resources.path 113 | * 114 | * @param path auth_resources.path, 资源地址 115 | */ 116 | public void setPath(String path) { 117 | this.path = path == null ? null : path.trim(); 118 | } 119 | 120 | /** 121 | * 获取 资源请求 字段:auth_resources.action 122 | * 123 | * @return auth_resources.action, 资源请求 124 | */ 125 | public String getAction() { 126 | return action; 127 | } 128 | 129 | /** 130 | * 设置 资源请求 字段:auth_resources.action 131 | * 132 | * @param action auth_resources.action, 资源请求 133 | */ 134 | public void setAction(String action) { 135 | this.action = action == null ? null : action.trim(); 136 | } 137 | 138 | /** 139 | * 获取 资源控制 字段:auth_resources.controller 140 | * 141 | * @return auth_resources.controller, 资源控制 142 | */ 143 | public String getController() { 144 | return controller; 145 | } 146 | 147 | /** 148 | * 设置 资源控制 字段:auth_resources.controller 149 | * 150 | * @param controller auth_resources.controller, 资源控制 151 | */ 152 | public void setController(String controller) { 153 | this.controller = controller == null ? null : controller.trim(); 154 | } 155 | 156 | /** 157 | * 获取 状态 字段:auth_resources.status 158 | * 159 | * @return auth_resources.status, 状态 160 | */ 161 | public Boolean getStatus() { 162 | return status; 163 | } 164 | 165 | /** 166 | * 设置 状态 字段:auth_resources.status 167 | * 168 | * @param status auth_resources.status, 状态 169 | */ 170 | public void setStatus(Boolean status) { 171 | this.status = status; 172 | } 173 | 174 | @Override 175 | public String toString() { 176 | return Objects.toStringHelper(this) 177 | .add("id", id) 178 | .add("name", name) 179 | .add("type", type) 180 | .add("path", path) 181 | .add("action", action) 182 | .add("controller", controller) 183 | .add("status", status) 184 | .toString(); 185 | } 186 | 187 | /** 188 | * ,auth_resources 189 | * 190 | * @param that 191 | */ 192 | @Override 193 | public boolean equals(Object that) { 194 | if (this == that) { 195 | return true; 196 | } 197 | if (that == null) { 198 | return false; 199 | } 200 | if (getClass() != that.getClass()) { 201 | return false; 202 | } 203 | Resources other = (Resources) that; 204 | return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) 205 | && (this.getName() == null ? other.getName() == null : this.getName().equals(other.getName())) 206 | && (this.getType() == null ? other.getType() == null : this.getType().equals(other.getType())) 207 | && (this.getPath() == null ? other.getPath() == null : this.getPath().equals(other.getPath())) 208 | && (this.getAction() == null ? other.getAction() == null : this.getAction().equals(other.getAction())) 209 | && (this.getController() == null ? other.getController() == null : this.getController().equals(other.getController())) 210 | && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus())); 211 | } 212 | 213 | /** 214 | * ,auth_resources 215 | */ 216 | @Override 217 | public int hashCode() { 218 | final int prime = 31; 219 | int result = 1; 220 | result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); 221 | result = prime * result + ((getName() == null) ? 0 : getName().hashCode()); 222 | result = prime * result + ((getType() == null) ? 0 : getType().hashCode()); 223 | result = prime * result + ((getPath() == null) ? 0 : getPath().hashCode()); 224 | result = prime * result + ((getAction() == null) ? 0 : getAction().hashCode()); 225 | result = prime * result + ((getController() == null) ? 0 : getController().hashCode()); 226 | result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode()); 227 | return result; 228 | } 229 | } -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/mvc/TableParamArgumentResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.mvc; 6 | 7 | import com.google.common.base.CaseFormat; 8 | import com.google.common.base.Strings; 9 | import com.google.common.collect.Lists; 10 | import org.mybatis.pagination.dto.datatables.PagingCriteria; 11 | import org.mybatis.pagination.dto.datatables.SearchField; 12 | import org.mybatis.pagination.dto.datatables.SortField; 13 | import org.springframework.core.MethodParameter; 14 | import org.springframework.web.bind.support.WebArgumentResolver; 15 | import org.springframework.web.context.request.NativeWebRequest; 16 | 17 | import javax.servlet.http.HttpServletRequest; 18 | import java.util.List; 19 | 20 | /** 21 | *

22 | * resolver paramArgument with annotation. 23 | *

24 | * 25 | * @author mumu @yfyang 26 | * @version 1.0 2013-09-05 10:44 PM 27 | * @see 28 | * @see 29 | * @since JDK 1.5 30 | */ 31 | public class TableParamArgumentResolver implements WebArgumentResolver { 32 | /** 33 | * Information for DataTables to use for rendering. 34 | */ 35 | private static final String S_ECHO = "sEcho"; 36 | /** 37 | * Display start point in the current data set. 38 | */ 39 | private static final String I_DISPLAY_START = "iDisplayStart"; 40 | /** 41 | * Number of records that the table can display in the current draw. 42 | * It is expected that the number of records returned will be equal to this number, unless the server has fewer records to return. 43 | */ 44 | private static final String I_DISPLAY_LENGTH = "iDisplayLength"; 45 | /** 46 | * Number of columns to sort on 47 | */ 48 | private static final String I_SORTING_COLS = "iSortingCols"; 49 | /** 50 | * Column being sorted on (you will need to decode this number for your database) 51 | */ 52 | private static final String I_SORT_COLS = "iSortCol_"; 53 | /** 54 | * Direction to be sorted - "desc" or "asc". 55 | */ 56 | private static final String S_SORT_DIR = "sSortDir_"; 57 | /** 58 | * The value specified by mDataProp for each column. 59 | * This can be useful for ensuring that the processing of data is independent from the order of the columns. 60 | */ 61 | private static final String S_DATA_PROP = "mDataProp_"; 62 | /** 63 | * Individual column filter 64 | */ 65 | private static final String S_SEACHE_VAL = "sSearch_"; 66 | /** 67 | * True if the individual column filter should be treated as a regular expression for advanced filtering, false if not 68 | */ 69 | private static final String B_REGEX = "bRegex_"; 70 | /** 71 | * Indicator for if a column is flagged as sortable or not on the client-side 72 | */ 73 | private static final String B_SORTTABLE = "bSortable_"; 74 | /** 75 | * Global search field value 76 | */ 77 | private static final String S_SEARCH = "sSearch"; 78 | /** 79 | * Number of columns being displayed (useful for getting individual column search info) 80 | */ 81 | private static final String I_COLUMNS = "iColumns"; 82 | /** 83 | * Hump Split colum name 84 | */ 85 | private final boolean humpSplit; 86 | 87 | /** 88 | * Instantiates a new Table param argument resolver. 89 | * 90 | * @param humpSplit the hump split 91 | */ 92 | public TableParamArgumentResolver(boolean humpSplit) { 93 | this.humpSplit = humpSplit; 94 | } 95 | 96 | 97 | @Override 98 | public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) throws Exception { 99 | TableParam tableParamAnnotation = methodParameter.getParameterAnnotation(TableParam.class); 100 | if (tableParamAnnotation != null) { 101 | HttpServletRequest httpRequest = (HttpServletRequest) webRequest.getNativeRequest(); 102 | 103 | String sEcho = httpRequest.getParameter(S_ECHO); 104 | String sDisplayStart = httpRequest.getParameter(I_DISPLAY_START); 105 | String sDisplayLength = httpRequest.getParameter(I_DISPLAY_LENGTH); 106 | 107 | int iEcho = Integer.parseInt(sEcho); 108 | int iDisplayStart = Integer.parseInt(sDisplayStart); 109 | int iDisplayLength = Integer.parseInt(sDisplayLength); 110 | 111 | List sortFields = getSortFileds(httpRequest); 112 | List searchFields = getSearchParam(httpRequest); 113 | 114 | return PagingCriteria.createCriteriaWithAllParamter(iDisplayStart, iDisplayLength, iEcho, sortFields, searchFields); 115 | } 116 | 117 | return WebArgumentResolver.UNRESOLVED; 118 | } 119 | 120 | /** 121 | * Gets sort fileds. 122 | * 123 | * @param httpRequest the http request 124 | * @return the sort fileds 125 | */ 126 | private List getSortFileds(final HttpServletRequest httpRequest) { 127 | 128 | String sSortingCols = httpRequest.getParameter(I_SORTING_COLS); 129 | 130 | int iSortingCols = Integer.parseInt(sSortingCols); 131 | final List sortFields = Lists.newArrayListWithCapacity(iSortingCols); 132 | String sSortDir; 133 | String sColName; 134 | String sSortCol; 135 | for (int colCount = 0; colCount < iSortingCols; colCount++) { 136 | sSortCol = httpRequest.getParameter(I_SORT_COLS + colCount); 137 | sSortDir = httpRequest.getParameter(S_SORT_DIR + colCount); 138 | sColName = httpRequest.getParameter(S_DATA_PROP + sSortCol); 139 | sColName = humpSplit 140 | ? CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, sColName) 141 | : sColName; 142 | sortFields.add(new SortField(sColName, sSortDir)); 143 | } 144 | return sortFields; 145 | } 146 | 147 | /** 148 | * Gets search param. 149 | * 150 | * @param httpRequest the http request 151 | * @return the search param 152 | */ 153 | private List getSearchParam(final HttpServletRequest httpRequest) { 154 | int iColumns = Integer.valueOf(httpRequest.getParameter(I_COLUMNS)); 155 | final List searchFields = Lists.newArrayListWithCapacity(iColumns); 156 | boolean regex; 157 | boolean searchable; 158 | String searchValue; 159 | String sColName; 160 | final String sSearch = httpRequest.getParameter(S_SEARCH); 161 | for (int col = 0; col < iColumns; col++) { 162 | searchValue = httpRequest.getParameter(S_SEACHE_VAL + col); 163 | sColName = httpRequest.getParameter(S_DATA_PROP + col); 164 | sColName = humpSplit 165 | ? CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, sColName) 166 | : sColName; 167 | if (!Strings.isNullOrEmpty(searchValue)) { 168 | regex = Boolean.valueOf(httpRequest.getParameter(B_REGEX + col)); 169 | searchable = Boolean.valueOf(httpRequest.getParameter(B_SORTTABLE + col)); 170 | searchFields.add(new SearchField(sColName, regex, searchable, searchValue)); 171 | } else if (!Strings.isNullOrEmpty(sSearch)) { 172 | searchFields.add(new SearchField(sColName, false, false, sSearch)); 173 | } 174 | } 175 | return searchFields; 176 | } 177 | 178 | } 179 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/dto/datatables/PagingCriteria.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination.dto.datatables; 6 | 7 | import java.util.Collections; 8 | import java.util.List; 9 | 10 | import com.google.common.collect.Lists; 11 | 12 | /** 13 | *

14 | * jQuery DataTables's PagingCriteria. 15 | *

16 | * 17 | * @author mumu@yfyang 18 | * @version 1.0 2013-09-05 10:37 PM 19 | * @since JDK 1.5 20 | */ 21 | public final class PagingCriteria { 22 | /** The constant DEFAULT_CRITERIA. */ 23 | private static final PagingCriteria DEFAULT_CRITERIA = new PagingCriteria(0, PagingCriteria.DEFAULT_SIZE, PagingCriteria.DEFAULT_SIZE); 24 | /** default page size. */ 25 | private static final int DEFAULT_SIZE = 10; 26 | /** start display */ 27 | private final int displayStart; 28 | /** disaplaySize */ 29 | private final int displaySize; 30 | /** sort fields */ 31 | private final List sortFields; 32 | /** search field information */ 33 | private final List searchFields; 34 | /** pageNumber */ 35 | private final int pageNumber; 36 | 37 | /** 38 | * Instantiates a new Paging criteria. 39 | * 40 | * @param displayStart the display start 41 | * @param displaySize the display size 42 | * @param pageNumber the page number 43 | * @param sortFields the sort fields 44 | * @param searchFields the search information 45 | */ 46 | private PagingCriteria(int displayStart 47 | , int displaySize 48 | , int pageNumber 49 | , List sortFields 50 | , List searchFields) { 51 | this.displayStart = displayStart; 52 | this.displaySize = displaySize; 53 | this.pageNumber = pageNumber; 54 | this.sortFields = sortFields; 55 | this.searchFields = searchFields; 56 | } 57 | 58 | /** 59 | * Instantiates a new Paging criteria and not sort\search. 60 | * 61 | * @param displaySize the display size 62 | * @param displayStart the display start 63 | * @param pageNumber the page number 64 | */ 65 | private PagingCriteria(int displaySize 66 | , int displayStart 67 | , int pageNumber) { 68 | this.displaySize = displaySize; 69 | this.displayStart = displayStart; 70 | this.pageNumber = pageNumber; 71 | this.searchFields = Lists.newArrayListWithCapacity(0); 72 | this.sortFields = Lists.newArrayListWithCapacity(0); 73 | } 74 | 75 | /** 76 | * Instantiates a new Paging criteria and no search. 77 | * 78 | * @param displaySize the display size 79 | * @param displayStart the display start 80 | * @param pageNumber the page number 81 | * @param sortFields the sort fields 82 | */ 83 | private PagingCriteria(int displaySize 84 | , int displayStart 85 | , int pageNumber 86 | , List sortFields) { 87 | this.sortFields = sortFields; 88 | this.displaySize = displaySize; 89 | this.displayStart = displayStart; 90 | this.pageNumber = pageNumber; 91 | this.searchFields = Lists.newArrayListWithCapacity(0); 92 | } 93 | 94 | /** 95 | * Instantiates a new Paging criteria and no sort. 96 | * 97 | * @param displayStart the display start 98 | * @param displaySize the display size 99 | * @param searchFields the search fields 100 | * @param pageNumber the page number 101 | */ 102 | private PagingCriteria(int displayStart 103 | , int displaySize 104 | , List searchFields 105 | , int pageNumber) { 106 | this.displayStart = displayStart; 107 | this.displaySize = displaySize; 108 | this.searchFields = searchFields; 109 | this.pageNumber = pageNumber; 110 | this.sortFields = Lists.newArrayListWithCapacity(0); 111 | } 112 | 113 | /** 114 | * Create criteria with all paramter. 115 | * 116 | * @param displayStart the display start 117 | * @param displaySize the display size 118 | * @param pageNumber the page number 119 | * @param sortFields the sort fields 120 | * @param searchFields the search fields 121 | * @return the paging criteria 122 | */ 123 | public static PagingCriteria createCriteriaWithAllParamter(int displayStart 124 | , int displaySize 125 | , int pageNumber 126 | , List sortFields 127 | , List searchFields) { 128 | return new PagingCriteria(displayStart, displaySize, pageNumber, sortFields, searchFields); 129 | } 130 | 131 | /** 132 | * Create criteria with sort. 133 | * 134 | * @param displayStart the display start 135 | * @param displaySize the display size 136 | * @param pageNumber the page number 137 | * @param sortFields the sort fields 138 | * @return the paging criteria 139 | */ 140 | public static PagingCriteria createCriteriaWithSort(int displayStart, int displaySize, int pageNumber 141 | , List sortFields) { 142 | return new PagingCriteria(displayStart, displaySize, pageNumber, sortFields); 143 | } 144 | 145 | /** 146 | * Create criteria with search. 147 | * 148 | * @param displayStart the display start 149 | * @param displaySize the display size 150 | * @param pageNumber the page number 151 | * @param searchFields the search fields 152 | * @return the paging criteria 153 | */ 154 | public static PagingCriteria createCriteriaWithSearch(int displayStart, int displaySize, int pageNumber 155 | , List searchFields) { 156 | return new PagingCriteria(displayStart, displaySize, searchFields, pageNumber); 157 | } 158 | 159 | /** 160 | * Create criteria. 161 | * 162 | * @param displayStart the display start 163 | * @param displaySize the display size 164 | * @param pageNumber the page number 165 | * @return the paging criteria 166 | */ 167 | public static PagingCriteria createCriteria(int displayStart, int displaySize, int pageNumber) { 168 | return new PagingCriteria(displayStart, displaySize, pageNumber); 169 | } 170 | 171 | /** 172 | * Get default criteria. 173 | * 174 | * @return the paging criteria 175 | */ 176 | public static PagingCriteria getDefaultCriteria() { 177 | return DEFAULT_CRITERIA; 178 | } 179 | 180 | /** 181 | * Gets display start. 182 | * 183 | * @return the display start 184 | */ 185 | public Integer getDisplayStart() { 186 | return displayStart; 187 | } 188 | 189 | /** 190 | * Gets display size. 191 | * 192 | * @return the display size 193 | */ 194 | public Integer getDisplaySize() { 195 | return displaySize; 196 | } 197 | 198 | /** 199 | * Gets search fields. 200 | * 201 | * @return the search fields 202 | */ 203 | public List getSearchFields() { 204 | if (this.searchFields == null) { 205 | return Lists.newArrayListWithCapacity(0); 206 | } 207 | return Collections.unmodifiableList(searchFields); 208 | } 209 | 210 | /** 211 | * Gets sort fields. 212 | * 213 | * @return the sort fields 214 | */ 215 | public List getSortFields() { 216 | if (this.sortFields == null) { 217 | return Lists.newArrayListWithCapacity(0); 218 | } 219 | return Collections.unmodifiableList(sortFields); 220 | } 221 | 222 | /** 223 | * Gets page number. 224 | * 225 | * @return the page number 226 | */ 227 | public Integer getPageNumber() { 228 | return pageNumber; 229 | } 230 | 231 | } 232 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | org.mybatis 7 | mybatis-pagination 8 | 0.0.3 9 | jar 10 | 11 | mybatis-paging 12 | http://maven.apache.org 13 | 14 | 15 | 16 | peak yfyang 17 | poplar1123@gmail.com 18 | 19 | 20 | 21 | 22 | UTF-8 23 | 3.2.2 24 | 3.2.4.RELEASE 25 | 1.2.0 26 | github 27 | 28 | 29 | 30 | 31 | 32 | 33 | com.google.guava 34 | guava 35 | 15.0 36 | 37 | 38 | org.mybatis 39 | mybatis 40 | ${mybatis.version} 41 | 42 | 43 | commons-beanutils 44 | commons-beanutils 45 | 1.8.3 46 | 47 | 48 | org.springframework 49 | spring-webmvc 50 | ${spring.version} 51 | provided 52 | 53 | 54 | javax.servlet 55 | servlet-api 56 | 2.5 57 | provided 58 | 59 | 60 | 61 | 62 | 63 | junit 64 | junit 65 | 4.10 66 | test 67 | 68 | 69 | org.springframework 70 | spring-context 71 | ${spring.version} 72 | test 73 | 74 | 75 | org.springframework 76 | spring-tx 77 | ${spring.version} 78 | test 79 | 80 | 81 | org.springframework 82 | spring-jdbc 83 | ${spring.version} 84 | test 85 | 86 | 87 | org.springframework 88 | spring-test 89 | ${spring.version} 90 | test 91 | 92 | 93 | org.mybatis 94 | mybatis-spring 95 | ${spring.mybatis.version} 96 | test 97 | 98 | 99 | mysql 100 | mysql-connector-java 101 | 5.1.20 102 | test 103 | 104 | 105 | net.sourceforge 106 | jtds 107 | 1.2.5 108 | test 109 | 110 | 111 | log4j 112 | log4j 113 | 1.2.16 114 | test 115 | 116 | 117 | com.alibaba 118 | druid 119 | 0.2.8 120 | test 121 | 122 | 123 | org.aspectj 124 | aspectjrt 125 | 1.7.2 126 | test 127 | 128 | 129 | c3p0 130 | c3p0 131 | 0.9.1.2 132 | test 133 | 134 | 135 | org.aspectj 136 | aspectjweaver 137 | 1.7.2 138 | test 139 | 140 | 141 | commons-dbcp 142 | commons-dbcp 143 | 1.4 144 | test 145 | 146 | 147 | 148 | io.github.yfyang 149 | sparta-helper 150 | 0.0.1 151 | 152 | 153 | 154 | 155 | 156 | mybatis-paging 157 | 158 | 159 | org.apache.maven.plugins 160 | maven-source-plugin 161 | 162 | true 163 | 164 | 165 | 166 | attach-sources 167 | 168 | jar 169 | 170 | 171 | 172 | 173 | 174 | maven-deploy-plugin 175 | 2.7 176 | 177 | internal.repo::default::file://${project.build.directory}/mvn-repo 178 | 179 | 180 | 181 | com.github.github 182 | site-maven-plugin 183 | 0.8 184 | 185 | Maven artifacts for ${project.version} 186 | true 187 | ${project.build.directory}/mvn-repo 188 | refs/heads/mvn-repo 189 | **/* 190 | mybatis-pagination 191 | yfyang 192 | 193 | 194 | 195 | 196 | 197 | site 198 | 199 | deploy 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | yfyang-mvn-repo 208 | https://raw.github.com/yfyang/sparta-helpers/mvn-repo/ 209 | 210 | true 211 | always 212 | 213 | 214 | 215 | 216 | 217 | github 218 | GitHub ${project.artifactId} Repository 219 | https://raw.github.com/yfyang/${project.artifactId}/mvn-repo 220 | 221 | 222 | 223 | -------------------------------------------------------------------------------- /src/main/java/org/mybatis/pagination/PaginationInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012-2013 mumu@yfyang. All Rights Reserved. 3 | */ 4 | 5 | package org.mybatis.pagination; 6 | 7 | import com.google.common.base.Joiner; 8 | import com.google.common.base.Preconditions; 9 | import com.google.common.collect.Lists; 10 | import io.github.sparta.helpers.reflex.Reflections; 11 | import io.github.sparta.helpers.sql.SqlRemoveHelper; 12 | import org.apache.ibatis.executor.Executor; 13 | import org.apache.ibatis.logging.Log; 14 | import org.apache.ibatis.logging.LogFactory; 15 | import org.apache.ibatis.mapping.BoundSql; 16 | import org.apache.ibatis.mapping.MappedStatement; 17 | import org.apache.ibatis.mapping.ParameterMapping; 18 | import org.apache.ibatis.mapping.SqlSource; 19 | import org.apache.ibatis.plugin.*; 20 | import org.apache.ibatis.session.ResultHandler; 21 | import org.apache.ibatis.session.RowBounds; 22 | import org.mybatis.pagination.dialect.DBMS; 23 | import org.mybatis.pagination.dialect.Dialect; 24 | import org.mybatis.pagination.dialect.DialectClient; 25 | import org.mybatis.pagination.dto.datatables.PagingCriteria; 26 | import org.mybatis.pagination.dto.datatables.SearchField; 27 | import org.mybatis.pagination.dto.datatables.SortField; 28 | import org.mybatis.pagination.helpers.CountHelper; 29 | import org.mybatis.pagination.helpers.StringHelper; 30 | 31 | import java.io.Serializable; 32 | import java.sql.Connection; 33 | import java.sql.SQLException; 34 | import java.util.List; 35 | import java.util.Properties; 36 | 37 | /** 38 | *

39 | * Mybatis数据库分页插件. 40 | * 拦截StatementHandler的prepare方法 41 | *

42 | * 43 | * @author poplar.yfyang 44 | * @version 1.0 2011-11-18 下午12:31 45 | * @since JDK 1.5 46 | */ 47 | @Intercepts({@Signature( 48 | type = Executor.class, 49 | method = "query", 50 | args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})}) 51 | public class PaginationInterceptor implements Interceptor, Serializable { 52 | /** serial Version */ 53 | private static final long serialVersionUID = -6075937069117597841L; 54 | private static final ThreadLocal PAGINATION_TOTAL = new ThreadLocal(); 55 | private static final ThreadLocal PAGE_REQUEST = new ThreadLocal(); 56 | /** logging */ 57 | private static final Log log = LogFactory.getLog(PaginationInterceptor.class); 58 | /** mapped statement parameter index. */ 59 | private static final int MAPPED_STATEMENT_INDEX = 0; 60 | /** sql id , in the mapper xml file. */ 61 | private static String _sql_regex = "[*]"; 62 | /** DataBase dialect. */ 63 | protected Dialect _dialect; 64 | 65 | /** 66 | * Gets pagination total. 67 | * 68 | * @return the pagination total 69 | */ 70 | public static int getPaginationTotal() { 71 | if (PAGINATION_TOTAL.get() == null) { 72 | return 0; 73 | } 74 | return PAGINATION_TOTAL.get(); 75 | } 76 | 77 | /** 78 | * Gets page request. 79 | * 80 | * @return the page request 81 | */ 82 | public static PagingCriteria getPageRequest() { 83 | return PAGE_REQUEST.get(); 84 | } 85 | 86 | /** clear total context. */ 87 | public static void clean() { 88 | PAGE_REQUEST.remove(); 89 | PAGINATION_TOTAL.remove(); 90 | } 91 | 92 | /** 93 | * Set the paging information,to RowBuounds. 94 | * 95 | * @param rowBounds rowBounds. 96 | * @return rowBounds. 97 | */ 98 | private static RowBounds offset_paging(RowBounds rowBounds, PagingCriteria pageRequest) { 99 | // rowBuounds has offset. 100 | if (rowBounds.getOffset() == RowBounds.NO_ROW_OFFSET) { 101 | if (pageRequest != null) { 102 | return new RowBounds(pageRequest.getDisplayStart(), pageRequest.getDisplaySize()); 103 | } 104 | } 105 | return rowBounds; 106 | } 107 | 108 | /** 109 | * Sort and filter sql. 110 | * 111 | * 112 | * @param sql the sql 113 | * @param pagingCriteria the paging criteria 114 | * @return the string 115 | */ 116 | private static String sortAndFilterSql(String sql, PagingCriteria pagingCriteria) { 117 | 118 | boolean order = SqlRemoveHelper.containOrder(sql); 119 | final List searchFields = pagingCriteria.getSearchFields(); 120 | if (searchFields != null && !searchFields.isEmpty()) { 121 | List where_field = Lists.newArrayList(); 122 | for (SearchField searchField : searchFields) { 123 | // fix inject sql 124 | where_field.add(searchField.getField() + StringHelper.LIKE_CHAR + StringHelper.likeValue(searchField.getValue())); 125 | } 126 | boolean where = SqlRemoveHelper.containWhere(sql); 127 | String orderBy = StringHelper.EMPTY; 128 | if (order) { 129 | String[] sqls = sql.split(SqlRemoveHelper.ORDER_REGEX); 130 | sql = sqls[0]; 131 | orderBy = CountHelper.SQL_ORDER + sqls[1]; 132 | } 133 | sql = String.format((where ? CountHelper.OR_SQL_FORMAT : CountHelper.WHERE_SQL_FORMAT), sql 134 | , Joiner.on(CountHelper.OR_JOINER).skipNulls().join(where_field), orderBy); 135 | } 136 | 137 | final List sortFields = pagingCriteria.getSortFields(); 138 | if (sortFields != null && !sortFields.isEmpty()) { 139 | List field_order = Lists.newArrayList(); 140 | for (SortField sortField : sortFields) { 141 | field_order.add(sortField.getField() + StringHelper.BLANK_CHAR + sortField.getDirection().getDirection()); 142 | } 143 | return String.format(order ? CountHelper.SQL_FORMAT : CountHelper.ORDER_SQL_FORMAT, sql 144 | , Joiner.on(StringHelper.DOT_CHAR).skipNulls().join(field_order)); 145 | } 146 | 147 | return sql; 148 | } 149 | 150 | /** 151 | * Copy from bound sql. 152 | * 153 | * @param ms the ms 154 | * @param boundSql the bound sql 155 | * @param sql the sql 156 | * @return the bound sql 157 | */ 158 | public static BoundSql copyFromBoundSql(MappedStatement ms, BoundSql boundSql, 159 | String sql) { 160 | BoundSql newBoundSql = new BoundSql(ms.getConfiguration(), sql, boundSql.getParameterMappings(), boundSql.getParameterObject()); 161 | for (ParameterMapping mapping : boundSql.getParameterMappings()) { 162 | String prop = mapping.getProperty(); 163 | if (boundSql.hasAdditionalParameter(prop)) { 164 | newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop)); 165 | } 166 | } 167 | return newBoundSql; 168 | } 169 | 170 | //see: MapperBuilderAssistant 171 | private static MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource) { 172 | MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType()); 173 | 174 | builder.resource(ms.getResource()); 175 | builder.fetchSize(ms.getFetchSize()); 176 | builder.statementType(ms.getStatementType()); 177 | builder.keyGenerator(ms.getKeyGenerator()); 178 | String[] keyProperties = ms.getKeyProperties(); 179 | builder.keyProperty(keyProperties == null ? null : keyProperties[0]); 180 | 181 | //setStatementTimeout() 182 | builder.timeout(ms.getTimeout()); 183 | 184 | //setStatementResultMap() 185 | builder.parameterMap(ms.getParameterMap()); 186 | 187 | //setStatementResultMap() 188 | builder.resultMaps(ms.getResultMaps()); 189 | builder.resultSetType(ms.getResultSetType()); 190 | 191 | //setStatementCache() 192 | builder.cache(ms.getCache()); 193 | builder.flushCacheRequired(ms.isFlushCacheRequired()); 194 | builder.useCache(ms.isUseCache()); 195 | 196 | return builder.build(); 197 | } 198 | 199 | /** 200 | * perform paging intercetion. 201 | * 202 | * @param queryArgs Executor.query params. 203 | */ 204 | private void processIntercept(final Object[] queryArgs) { 205 | final MappedStatement ms = (MappedStatement) queryArgs[MAPPED_STATEMENT_INDEX]; 206 | final Object parameter = queryArgs[1]; 207 | 208 | //the need for paging intercept. 209 | boolean interceptor = ms.getId().matches(_sql_regex); 210 | //obtain paging information. 211 | final PagingCriteria pageRequest = interceptor 212 | ? PagingParametersFinder.instance.findCriteria(parameter) 213 | : PagingCriteria.getDefaultCriteria(); 214 | PAGE_REQUEST.set(pageRequest); 215 | 216 | final RowBounds oldRow = (RowBounds) queryArgs[2]; 217 | final RowBounds rowBounds = (interceptor) ? offset_paging(oldRow, pageRequest) : oldRow; 218 | int offset = rowBounds.getOffset(); 219 | int limit = rowBounds.getLimit(); 220 | 221 | if (_dialect.supportsLimit() && (offset != RowBounds.NO_ROW_OFFSET || limit != RowBounds.NO_ROW_LIMIT)) { 222 | final BoundSql boundSql = ms.getBoundSql(parameter); 223 | String sql = boundSql.getSql().trim(); 224 | 225 | Connection connection = null; 226 | try { 227 | //get connection 228 | connection = ms.getConfiguration().getEnvironment().getDataSource().getConnection(); 229 | int count = CountHelper.getCount(sql, connection, ms, parameter, boundSql, _dialect); 230 | PAGINATION_TOTAL.set(count); 231 | } catch (SQLException e) { 232 | log.error("The total number of access to the database failure.", e); 233 | } finally { 234 | try { 235 | if (connection != null && !connection.isClosed()) { 236 | connection.close(); 237 | } 238 | } catch (SQLException e) { 239 | log.error("Close the database connection error.", e); 240 | } 241 | } 242 | String new_sql = sortAndFilterSql(sql, pageRequest); 243 | if (_dialect.supportsLimit()) { 244 | new_sql = _dialect.getLimitString(new_sql, offset, limit); 245 | offset = RowBounds.NO_ROW_OFFSET; 246 | } else { 247 | new_sql = _dialect.getLimitString(new_sql, 0, limit); 248 | } 249 | if (log.isDebugEnabled()) { 250 | log.debug("pagination sql is :[" + new_sql + "]"); 251 | } 252 | limit = RowBounds.NO_ROW_LIMIT; 253 | 254 | queryArgs[2] = new RowBounds(offset, limit); 255 | 256 | BoundSql newBoundSql = copyFromBoundSql(ms, boundSql, new_sql); 257 | 258 | MappedStatement newMs = copyFromMappedStatement(ms, new BoundSqlSqlSource(newBoundSql)); 259 | queryArgs[MAPPED_STATEMENT_INDEX] = newMs; 260 | } 261 | } 262 | 263 | @Override 264 | public Object intercept(Invocation invocation) throws Throwable { 265 | processIntercept(invocation.getArgs()); 266 | return invocation.proceed(); 267 | } 268 | 269 | @Override 270 | public Object plugin(Object o) { 271 | 272 | if (Executor.class.isAssignableFrom(o.getClass())) { 273 | return Plugin.wrap(new PaginationExecutor((Executor) o), this); 274 | } 275 | return Plugin.wrap(o, this); 276 | 277 | } 278 | 279 | /** 280 | * 设置属性,支持自定义方言类和制定数据库的方式 281 | *

282 | * dialectClass,自定义方言类。可以不配置这项 283 | * dbms 数据库类型,插件支持的数据库 284 | * sqlRegex 需要拦截的SQL ID 285 | *

286 | * 如果同时配置了dialectClassdbms,则以dbms为主 287 | * 288 | * @param p 属性 289 | */ 290 | @Override 291 | public void setProperties(Properties p) { 292 | String dialectClass = p.getProperty("dialectClass"); 293 | DBMS dbms; 294 | if (StringHelper.isEmpty(dialectClass)) { 295 | String dialect = p.getProperty("dbms"); 296 | Preconditions.checkArgument(!StringHelper.isEmpty(dialect), "dialect property is not found!"); 297 | dbms = DBMS.valueOf(dialect.toUpperCase()); 298 | Preconditions.checkNotNull(dbms, "plugin not super on this database."); 299 | } else { 300 | Dialect dialect1 = (Dialect) Reflections.instance(dialectClass); 301 | Preconditions.checkNotNull(dialect1, "dialectClass is not found!"); 302 | DialectClient.putEx(dialect1); 303 | dbms = DBMS.EX; 304 | } 305 | 306 | 307 | _dialect = DialectClient.getDbmsDialect(dbms); 308 | 309 | String sql_regex = p.getProperty("sqlRegex"); 310 | if (!StringHelper.isEmpty(sql_regex)) { 311 | _sql_regex = sql_regex; 312 | } 313 | clean(); 314 | } 315 | 316 | public static class BoundSqlSqlSource implements SqlSource { 317 | BoundSql boundSql; 318 | 319 | public BoundSqlSqlSource(BoundSql boundSql) { 320 | this.boundSql = boundSql; 321 | } 322 | 323 | public BoundSql getBoundSql(Object parameterObject) { 324 | return boundSql; 325 | } 326 | } 327 | } 328 | -------------------------------------------------------------------------------- /src/test/resources/mapper/ResourcesMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | and ${criterion.condition} 30 | 31 | 32 | and ${criterion.condition} #{criterion.value} 33 | 34 | 35 | and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} 36 | 37 | 38 | and ${criterion.condition} 39 | 41 | #{listItem} 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | and ${criterion.condition} 64 | 65 | 66 | and ${criterion.condition} #{criterion.value} 67 | 68 | 69 | and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} 70 | 71 | 72 | and ${criterion.condition} 73 | 75 | #{listItem} 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 90 | id, name, type, path, action, controller, status 91 | 92 | 110 | 120 | 121 | 125 | delete from res 126 | where id = #{id,jdbcType=VARCHAR} 127 | 128 | 129 | 133 | delete from res 134 | 135 | 136 | 137 | 138 | 139 | 143 | insert into res (id, name, type, 144 | path, action, controller, 145 | status) 146 | values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, 147 | #{path,jdbcType=VARCHAR}, #{action,jdbcType=VARCHAR}, #{controller,jdbcType=VARCHAR}, 148 | #{status,jdbcType=BIT}) 149 | 150 | 151 | 155 | insert into res 156 | 157 | 158 | id, 159 | 160 | 161 | name, 162 | 163 | 164 | type, 165 | 166 | 167 | path, 168 | 169 | 170 | action, 171 | 172 | 173 | controller, 174 | 175 | 176 | status, 177 | 178 | 179 | 180 | 181 | #{id,jdbcType=VARCHAR}, 182 | 183 | 184 | #{name,jdbcType=VARCHAR}, 185 | 186 | 187 | #{type,jdbcType=VARCHAR}, 188 | 189 | 190 | #{path,jdbcType=VARCHAR}, 191 | 192 | 193 | #{action,jdbcType=VARCHAR}, 194 | 195 | 196 | #{controller,jdbcType=VARCHAR}, 197 | 198 | 199 | #{status,jdbcType=BIT}, 200 | 201 | 202 | 203 | 204 | 208 | update res 209 | 210 | 211 | id = #{record.id,jdbcType=VARCHAR}, 212 | 213 | 214 | name = #{record.name,jdbcType=VARCHAR}, 215 | 216 | 217 | type = #{record.type,jdbcType=VARCHAR}, 218 | 219 | 220 | path = #{record.path,jdbcType=VARCHAR}, 221 | 222 | 223 | action = #{record.action,jdbcType=VARCHAR}, 224 | 225 | 226 | controller = #{record.controller,jdbcType=VARCHAR}, 227 | 228 | 229 | status = #{record.status,jdbcType=BIT}, 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 241 | update res 242 | set id = #{record.id,jdbcType=VARCHAR}, 243 | name = #{record.name,jdbcType=VARCHAR}, 244 | type = #{record.type,jdbcType=VARCHAR}, 245 | path = #{record.path,jdbcType=VARCHAR}, 246 | action = #{record.action,jdbcType=VARCHAR}, 247 | controller = #{record.controller,jdbcType=VARCHAR}, 248 | status = #{record.status,jdbcType=BIT} 249 | 250 | 251 | 252 | 253 | 254 | 258 | update res 259 | 260 | 261 | name = #{name,jdbcType=VARCHAR}, 262 | 263 | 264 | type = #{type,jdbcType=VARCHAR}, 265 | 266 | 267 | path = #{path,jdbcType=VARCHAR}, 268 | 269 | 270 | action = #{action,jdbcType=VARCHAR}, 271 | 272 | 273 | controller = #{controller,jdbcType=VARCHAR}, 274 | 275 | 276 | status = #{status,jdbcType=BIT}, 277 | 278 | 279 | where id = #{id,jdbcType=VARCHAR} 280 | 281 | 282 | 286 | update res 287 | set name = #{name,jdbcType=VARCHAR}, 288 | type = #{type,jdbcType=VARCHAR}, 289 | path = #{path,jdbcType=VARCHAR}, 290 | action = #{action,jdbcType=VARCHAR}, 291 | controller = #{controller,jdbcType=VARCHAR}, 292 | status = #{status,jdbcType=BIT} 293 | where id = #{id,jdbcType=VARCHAR} 294 | 295 | 296 | 299 | 300 | 303 | 306 | -------------------------------------------------------------------------------- /src/test/java/org/mybatis/pagination/domain/ResourcesCriteria.java: -------------------------------------------------------------------------------- 1 | package org.mybatis.pagination.domain; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class ResourcesCriteria { 7 | /** 8 | * 排序字段,auth_resources 9 | */ 10 | protected String orderByClause; 11 | 12 | /** 13 | * 是否过滤重复数据,auth_resources 14 | */ 15 | protected boolean distinct; 16 | 17 | /** 18 | * ,auth_resources 19 | */ 20 | protected List oredCriteria; 21 | 22 | /** 23 | * 构造查询条件,auth_resources 24 | */ 25 | public ResourcesCriteria() { 26 | oredCriteria = new ArrayList(); 27 | } 28 | 29 | /** 30 | * 为系统资源设置排序字段,auth_resources 31 | * 32 | * @param orderByClause 排序字段 33 | */ 34 | public void setOrderByClause(String orderByClause) { 35 | this.orderByClause = orderByClause; 36 | } 37 | 38 | /** 39 | * 获取排序字段,auth_resources 40 | */ 41 | public String getOrderByClause() { 42 | return orderByClause; 43 | } 44 | 45 | /** 46 | * 为系统资源设置过滤重复数据,auth_resources 47 | * 48 | * @param distinct 是否过滤重复数据 49 | */ 50 | public void setDistinct(boolean distinct) { 51 | this.distinct = distinct; 52 | } 53 | 54 | /** 55 | * 是否过滤重复数据,auth_resources 56 | */ 57 | public boolean isDistinct() { 58 | return distinct; 59 | } 60 | 61 | /** 62 | * 获取当前的查询条件实例,auth_resources 63 | */ 64 | public List getOredCriteria() { 65 | return oredCriteria; 66 | } 67 | 68 | /** 69 | * ,auth_resources 70 | * 71 | * @param criteria 过滤条件实例 72 | */ 73 | public void or(Criteria criteria) { 74 | oredCriteria.add(criteria); 75 | } 76 | 77 | /** 78 | * ,auth_resources 79 | */ 80 | public Criteria or() { 81 | Criteria criteria = createCriteriaInternal(); 82 | oredCriteria.add(criteria); 83 | return criteria; 84 | } 85 | 86 | /** 87 | * 为系统资源创建一个查询条件,auth_resources 88 | */ 89 | public Criteria createCriteria() { 90 | Criteria criteria = createCriteriaInternal(); 91 | if (oredCriteria.size() == 0) { 92 | oredCriteria.add(criteria); 93 | } 94 | return criteria; 95 | } 96 | 97 | /** 98 | * 内部构建查询条件对象,auth_resources 99 | */ 100 | protected Criteria createCriteriaInternal() { 101 | Criteria criteria = new Criteria(); 102 | return criteria; 103 | } 104 | 105 | /** 106 | * 清除查询条件,auth_resources 107 | */ 108 | public void clear() { 109 | oredCriteria.clear(); 110 | orderByClause = null; 111 | distinct = false; 112 | } 113 | 114 | /** 115 | * 基本动态SQL对象,auth_resources 116 | */ 117 | protected abstract static class GeneratedCriteria { 118 | protected List criteria; 119 | 120 | protected GeneratedCriteria() { 121 | super(); 122 | criteria = new ArrayList(); 123 | } 124 | 125 | public boolean isValid() { 126 | return criteria.size() > 0; 127 | } 128 | 129 | public List getAllCriteria() { 130 | return criteria; 131 | } 132 | 133 | public List getCriteria() { 134 | return criteria; 135 | } 136 | 137 | protected void addCriterion(String condition) { 138 | if (condition == null) { 139 | throw new RuntimeException("Value for condition cannot be null"); 140 | } 141 | criteria.add(new Criterion(condition)); 142 | } 143 | 144 | protected void addCriterion(String condition, Object value, String property) { 145 | if (value == null) { 146 | throw new RuntimeException("Value for " + property + " cannot be null"); 147 | } 148 | criteria.add(new Criterion(condition, value)); 149 | } 150 | 151 | protected void addCriterion(String condition, Object value1, Object value2, String property) { 152 | if (value1 == null || value2 == null) { 153 | throw new RuntimeException("Between values for " + property + " cannot be null"); 154 | } 155 | criteria.add(new Criterion(condition, value1, value2)); 156 | } 157 | 158 | public Criteria andIdIsNull() { 159 | addCriterion("id is null"); 160 | return (Criteria) this; 161 | } 162 | 163 | public Criteria andIdIsNotNull() { 164 | addCriterion("id is not null"); 165 | return (Criteria) this; 166 | } 167 | 168 | public Criteria andIdEqualTo(String value) { 169 | addCriterion("id =", value, "id"); 170 | return (Criteria) this; 171 | } 172 | 173 | public Criteria andIdNotEqualTo(String value) { 174 | addCriterion("id <>", value, "id"); 175 | return (Criteria) this; 176 | } 177 | 178 | public Criteria andIdGreaterThan(String value) { 179 | addCriterion("id >", value, "id"); 180 | return (Criteria) this; 181 | } 182 | 183 | public Criteria andIdGreaterThanOrEqualTo(String value) { 184 | addCriterion("id >=", value, "id"); 185 | return (Criteria) this; 186 | } 187 | 188 | public Criteria andIdLessThan(String value) { 189 | addCriterion("id <", value, "id"); 190 | return (Criteria) this; 191 | } 192 | 193 | public Criteria andIdLessThanOrEqualTo(String value) { 194 | addCriterion("id <=", value, "id"); 195 | return (Criteria) this; 196 | } 197 | 198 | public Criteria andIdLike(String value) { 199 | addCriterion("id like", value, "id"); 200 | return (Criteria) this; 201 | } 202 | 203 | public Criteria andIdNotLike(String value) { 204 | addCriterion("id not like", value, "id"); 205 | return (Criteria) this; 206 | } 207 | 208 | public Criteria andIdIn(List values) { 209 | addCriterion("id in", values, "id"); 210 | return (Criteria) this; 211 | } 212 | 213 | public Criteria andIdNotIn(List values) { 214 | addCriterion("id not in", values, "id"); 215 | return (Criteria) this; 216 | } 217 | 218 | public Criteria andIdBetween(String value1, String value2) { 219 | addCriterion("id between", value1, value2, "id"); 220 | return (Criteria) this; 221 | } 222 | 223 | public Criteria andIdNotBetween(String value1, String value2) { 224 | addCriterion("id not between", value1, value2, "id"); 225 | return (Criteria) this; 226 | } 227 | 228 | public Criteria andNameIsNull() { 229 | addCriterion("name is null"); 230 | return (Criteria) this; 231 | } 232 | 233 | public Criteria andNameIsNotNull() { 234 | addCriterion("name is not null"); 235 | return (Criteria) this; 236 | } 237 | 238 | public Criteria andNameEqualTo(String value) { 239 | addCriterion("name =", value, "name"); 240 | return (Criteria) this; 241 | } 242 | 243 | public Criteria andNameNotEqualTo(String value) { 244 | addCriterion("name <>", value, "name"); 245 | return (Criteria) this; 246 | } 247 | 248 | public Criteria andNameGreaterThan(String value) { 249 | addCriterion("name >", value, "name"); 250 | return (Criteria) this; 251 | } 252 | 253 | public Criteria andNameGreaterThanOrEqualTo(String value) { 254 | addCriterion("name >=", value, "name"); 255 | return (Criteria) this; 256 | } 257 | 258 | public Criteria andNameLessThan(String value) { 259 | addCriterion("name <", value, "name"); 260 | return (Criteria) this; 261 | } 262 | 263 | public Criteria andNameLessThanOrEqualTo(String value) { 264 | addCriterion("name <=", value, "name"); 265 | return (Criteria) this; 266 | } 267 | 268 | public Criteria andNameLike(String value) { 269 | addCriterion("name like", value, "name"); 270 | return (Criteria) this; 271 | } 272 | 273 | public Criteria andNameNotLike(String value) { 274 | addCriterion("name not like", value, "name"); 275 | return (Criteria) this; 276 | } 277 | 278 | public Criteria andNameIn(List values) { 279 | addCriterion("name in", values, "name"); 280 | return (Criteria) this; 281 | } 282 | 283 | public Criteria andNameNotIn(List values) { 284 | addCriterion("name not in", values, "name"); 285 | return (Criteria) this; 286 | } 287 | 288 | public Criteria andNameBetween(String value1, String value2) { 289 | addCriterion("name between", value1, value2, "name"); 290 | return (Criteria) this; 291 | } 292 | 293 | public Criteria andNameNotBetween(String value1, String value2) { 294 | addCriterion("name not between", value1, value2, "name"); 295 | return (Criteria) this; 296 | } 297 | 298 | public Criteria andTypeIsNull() { 299 | addCriterion("type is null"); 300 | return (Criteria) this; 301 | } 302 | 303 | public Criteria andTypeIsNotNull() { 304 | addCriterion("type is not null"); 305 | return (Criteria) this; 306 | } 307 | 308 | public Criteria andTypeEqualTo(String value) { 309 | addCriterion("type =", value, "type"); 310 | return (Criteria) this; 311 | } 312 | 313 | public Criteria andTypeNotEqualTo(String value) { 314 | addCriterion("type <>", value, "type"); 315 | return (Criteria) this; 316 | } 317 | 318 | public Criteria andTypeGreaterThan(String value) { 319 | addCriterion("type >", value, "type"); 320 | return (Criteria) this; 321 | } 322 | 323 | public Criteria andTypeGreaterThanOrEqualTo(String value) { 324 | addCriterion("type >=", value, "type"); 325 | return (Criteria) this; 326 | } 327 | 328 | public Criteria andTypeLessThan(String value) { 329 | addCriterion("type <", value, "type"); 330 | return (Criteria) this; 331 | } 332 | 333 | public Criteria andTypeLessThanOrEqualTo(String value) { 334 | addCriterion("type <=", value, "type"); 335 | return (Criteria) this; 336 | } 337 | 338 | public Criteria andTypeLike(String value) { 339 | addCriterion("type like", value, "type"); 340 | return (Criteria) this; 341 | } 342 | 343 | public Criteria andTypeNotLike(String value) { 344 | addCriterion("type not like", value, "type"); 345 | return (Criteria) this; 346 | } 347 | 348 | public Criteria andTypeIn(List values) { 349 | addCriterion("type in", values, "type"); 350 | return (Criteria) this; 351 | } 352 | 353 | public Criteria andTypeNotIn(List values) { 354 | addCriterion("type not in", values, "type"); 355 | return (Criteria) this; 356 | } 357 | 358 | public Criteria andTypeBetween(String value1, String value2) { 359 | addCriterion("type between", value1, value2, "type"); 360 | return (Criteria) this; 361 | } 362 | 363 | public Criteria andTypeNotBetween(String value1, String value2) { 364 | addCriterion("type not between", value1, value2, "type"); 365 | return (Criteria) this; 366 | } 367 | 368 | public Criteria andPathIsNull() { 369 | addCriterion("path is null"); 370 | return (Criteria) this; 371 | } 372 | 373 | public Criteria andPathIsNotNull() { 374 | addCriterion("path is not null"); 375 | return (Criteria) this; 376 | } 377 | 378 | public Criteria andPathEqualTo(String value) { 379 | addCriterion("path =", value, "path"); 380 | return (Criteria) this; 381 | } 382 | 383 | public Criteria andPathNotEqualTo(String value) { 384 | addCriterion("path <>", value, "path"); 385 | return (Criteria) this; 386 | } 387 | 388 | public Criteria andPathGreaterThan(String value) { 389 | addCriterion("path >", value, "path"); 390 | return (Criteria) this; 391 | } 392 | 393 | public Criteria andPathGreaterThanOrEqualTo(String value) { 394 | addCriterion("path >=", value, "path"); 395 | return (Criteria) this; 396 | } 397 | 398 | public Criteria andPathLessThan(String value) { 399 | addCriterion("path <", value, "path"); 400 | return (Criteria) this; 401 | } 402 | 403 | public Criteria andPathLessThanOrEqualTo(String value) { 404 | addCriterion("path <=", value, "path"); 405 | return (Criteria) this; 406 | } 407 | 408 | public Criteria andPathLike(String value) { 409 | addCriterion("path like", value, "path"); 410 | return (Criteria) this; 411 | } 412 | 413 | public Criteria andPathNotLike(String value) { 414 | addCriterion("path not like", value, "path"); 415 | return (Criteria) this; 416 | } 417 | 418 | public Criteria andPathIn(List values) { 419 | addCriterion("path in", values, "path"); 420 | return (Criteria) this; 421 | } 422 | 423 | public Criteria andPathNotIn(List values) { 424 | addCriterion("path not in", values, "path"); 425 | return (Criteria) this; 426 | } 427 | 428 | public Criteria andPathBetween(String value1, String value2) { 429 | addCriterion("path between", value1, value2, "path"); 430 | return (Criteria) this; 431 | } 432 | 433 | public Criteria andPathNotBetween(String value1, String value2) { 434 | addCriterion("path not between", value1, value2, "path"); 435 | return (Criteria) this; 436 | } 437 | 438 | public Criteria andActionIsNull() { 439 | addCriterion("action is null"); 440 | return (Criteria) this; 441 | } 442 | 443 | public Criteria andActionIsNotNull() { 444 | addCriterion("action is not null"); 445 | return (Criteria) this; 446 | } 447 | 448 | public Criteria andActionEqualTo(String value) { 449 | addCriterion("action =", value, "action"); 450 | return (Criteria) this; 451 | } 452 | 453 | public Criteria andActionNotEqualTo(String value) { 454 | addCriterion("action <>", value, "action"); 455 | return (Criteria) this; 456 | } 457 | 458 | public Criteria andActionGreaterThan(String value) { 459 | addCriterion("action >", value, "action"); 460 | return (Criteria) this; 461 | } 462 | 463 | public Criteria andActionGreaterThanOrEqualTo(String value) { 464 | addCriterion("action >=", value, "action"); 465 | return (Criteria) this; 466 | } 467 | 468 | public Criteria andActionLessThan(String value) { 469 | addCriterion("action <", value, "action"); 470 | return (Criteria) this; 471 | } 472 | 473 | public Criteria andActionLessThanOrEqualTo(String value) { 474 | addCriterion("action <=", value, "action"); 475 | return (Criteria) this; 476 | } 477 | 478 | public Criteria andActionLike(String value) { 479 | addCriterion("action like", value, "action"); 480 | return (Criteria) this; 481 | } 482 | 483 | public Criteria andActionNotLike(String value) { 484 | addCriterion("action not like", value, "action"); 485 | return (Criteria) this; 486 | } 487 | 488 | public Criteria andActionIn(List values) { 489 | addCriterion("action in", values, "action"); 490 | return (Criteria) this; 491 | } 492 | 493 | public Criteria andActionNotIn(List values) { 494 | addCriterion("action not in", values, "action"); 495 | return (Criteria) this; 496 | } 497 | 498 | public Criteria andActionBetween(String value1, String value2) { 499 | addCriterion("action between", value1, value2, "action"); 500 | return (Criteria) this; 501 | } 502 | 503 | public Criteria andActionNotBetween(String value1, String value2) { 504 | addCriterion("action not between", value1, value2, "action"); 505 | return (Criteria) this; 506 | } 507 | 508 | public Criteria andControllerIsNull() { 509 | addCriterion("controller is null"); 510 | return (Criteria) this; 511 | } 512 | 513 | public Criteria andControllerIsNotNull() { 514 | addCriterion("controller is not null"); 515 | return (Criteria) this; 516 | } 517 | 518 | public Criteria andControllerEqualTo(String value) { 519 | addCriterion("controller =", value, "controller"); 520 | return (Criteria) this; 521 | } 522 | 523 | public Criteria andControllerNotEqualTo(String value) { 524 | addCriterion("controller <>", value, "controller"); 525 | return (Criteria) this; 526 | } 527 | 528 | public Criteria andControllerGreaterThan(String value) { 529 | addCriterion("controller >", value, "controller"); 530 | return (Criteria) this; 531 | } 532 | 533 | public Criteria andControllerGreaterThanOrEqualTo(String value) { 534 | addCriterion("controller >=", value, "controller"); 535 | return (Criteria) this; 536 | } 537 | 538 | public Criteria andControllerLessThan(String value) { 539 | addCriterion("controller <", value, "controller"); 540 | return (Criteria) this; 541 | } 542 | 543 | public Criteria andControllerLessThanOrEqualTo(String value) { 544 | addCriterion("controller <=", value, "controller"); 545 | return (Criteria) this; 546 | } 547 | 548 | public Criteria andControllerLike(String value) { 549 | addCriterion("controller like", value, "controller"); 550 | return (Criteria) this; 551 | } 552 | 553 | public Criteria andControllerNotLike(String value) { 554 | addCriterion("controller not like", value, "controller"); 555 | return (Criteria) this; 556 | } 557 | 558 | public Criteria andControllerIn(List values) { 559 | addCriterion("controller in", values, "controller"); 560 | return (Criteria) this; 561 | } 562 | 563 | public Criteria andControllerNotIn(List values) { 564 | addCriterion("controller not in", values, "controller"); 565 | return (Criteria) this; 566 | } 567 | 568 | public Criteria andControllerBetween(String value1, String value2) { 569 | addCriterion("controller between", value1, value2, "controller"); 570 | return (Criteria) this; 571 | } 572 | 573 | public Criteria andControllerNotBetween(String value1, String value2) { 574 | addCriterion("controller not between", value1, value2, "controller"); 575 | return (Criteria) this; 576 | } 577 | 578 | public Criteria andStatusIsNull() { 579 | addCriterion("status is null"); 580 | return (Criteria) this; 581 | } 582 | 583 | public Criteria andStatusIsNotNull() { 584 | addCriterion("status is not null"); 585 | return (Criteria) this; 586 | } 587 | 588 | public Criteria andStatusEqualTo(Boolean value) { 589 | addCriterion("status =", value, "status"); 590 | return (Criteria) this; 591 | } 592 | 593 | public Criteria andStatusNotEqualTo(Boolean value) { 594 | addCriterion("status <>", value, "status"); 595 | return (Criteria) this; 596 | } 597 | 598 | public Criteria andStatusGreaterThan(Boolean value) { 599 | addCriterion("status >", value, "status"); 600 | return (Criteria) this; 601 | } 602 | 603 | public Criteria andStatusGreaterThanOrEqualTo(Boolean value) { 604 | addCriterion("status >=", value, "status"); 605 | return (Criteria) this; 606 | } 607 | 608 | public Criteria andStatusLessThan(Boolean value) { 609 | addCriterion("status <", value, "status"); 610 | return (Criteria) this; 611 | } 612 | 613 | public Criteria andStatusLessThanOrEqualTo(Boolean value) { 614 | addCriterion("status <=", value, "status"); 615 | return (Criteria) this; 616 | } 617 | 618 | public Criteria andStatusIn(List values) { 619 | addCriterion("status in", values, "status"); 620 | return (Criteria) this; 621 | } 622 | 623 | public Criteria andStatusNotIn(List values) { 624 | addCriterion("status not in", values, "status"); 625 | return (Criteria) this; 626 | } 627 | 628 | public Criteria andStatusBetween(Boolean value1, Boolean value2) { 629 | addCriterion("status between", value1, value2, "status"); 630 | return (Criteria) this; 631 | } 632 | 633 | public Criteria andStatusNotBetween(Boolean value1, Boolean value2) { 634 | addCriterion("status not between", value1, value2, "status"); 635 | return (Criteria) this; 636 | } 637 | } 638 | 639 | /** 640 | * 数据库表 auth_resources映射实体 641 | */ 642 | public static class Criteria extends GeneratedCriteria { 643 | 644 | protected Criteria() { 645 | super(); 646 | } 647 | } 648 | 649 | /** 650 | * 动态SQL对象,auth_resources 651 | */ 652 | public static class Criterion { 653 | private String condition; 654 | 655 | private Object value; 656 | 657 | private Object secondValue; 658 | 659 | private boolean noValue; 660 | 661 | private boolean singleValue; 662 | 663 | private boolean betweenValue; 664 | 665 | private boolean listValue; 666 | 667 | private String typeHandler; 668 | 669 | public String getCondition() { 670 | return condition; 671 | } 672 | 673 | public Object getValue() { 674 | return value; 675 | } 676 | 677 | public Object getSecondValue() { 678 | return secondValue; 679 | } 680 | 681 | public boolean isNoValue() { 682 | return noValue; 683 | } 684 | 685 | public boolean isSingleValue() { 686 | return singleValue; 687 | } 688 | 689 | public boolean isBetweenValue() { 690 | return betweenValue; 691 | } 692 | 693 | public boolean isListValue() { 694 | return listValue; 695 | } 696 | 697 | public String getTypeHandler() { 698 | return typeHandler; 699 | } 700 | 701 | protected Criterion(String condition) { 702 | super(); 703 | this.condition = condition; 704 | this.typeHandler = null; 705 | this.noValue = true; 706 | } 707 | 708 | protected Criterion(String condition, Object value, String typeHandler) { 709 | super(); 710 | this.condition = condition; 711 | this.value = value; 712 | this.typeHandler = typeHandler; 713 | if (value instanceof List) { 714 | this.listValue = true; 715 | } else { 716 | this.singleValue = true; 717 | } 718 | } 719 | 720 | protected Criterion(String condition, Object value) { 721 | this(condition, value, null); 722 | } 723 | 724 | protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { 725 | super(); 726 | this.condition = condition; 727 | this.value = value; 728 | this.secondValue = secondValue; 729 | this.typeHandler = typeHandler; 730 | this.betweenValue = true; 731 | } 732 | 733 | protected Criterion(String condition, Object value, Object secondValue) { 734 | this(condition, value, secondValue, null); 735 | } 736 | } 737 | } --------------------------------------------------------------------------------