Skip to content

Commit d3aaa06

Browse files
author
Stephen.lin
committed
init
0 parents  commit d3aaa06

File tree

7 files changed

+429
-0
lines changed

7 files changed

+429
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#### mybatis 分页插件
2+
3+
基于 exectur 拦截 查询请求

pom.xml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<groupId>com.zuicoding.platform</groupId>
6+
<artifactId>mybatis-pagination</artifactId>
7+
<version>0.0.1-SNAPSHOTS</version>
8+
<packaging>jar</packaging>
9+
10+
<name>mybatis-pagination</name>
11+
<url>http://maven.apache.org</url>
12+
13+
<properties>
14+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15+
<log.version>1.7.25</log.version>
16+
</properties>
17+
18+
<dependencies>
19+
<dependency>
20+
<groupId>org.mybatis</groupId>
21+
<artifactId>mybatis</artifactId>
22+
<version>3.4.4</version>
23+
</dependency>
24+
<dependency>
25+
<groupId>org.slf4j</groupId>
26+
<artifactId>slf4j-api</artifactId>
27+
<version>${log.version}</version>
28+
</dependency>
29+
<dependency>
30+
<groupId>org.slf4j</groupId>
31+
<artifactId>slf4j-log4j12</artifactId>
32+
<version>${log.version}</version>
33+
</dependency>
34+
<dependency>
35+
<groupId>junit</groupId>
36+
<artifactId>junit</artifactId>
37+
<version>4.12</version>
38+
<scope>test</scope>
39+
</dependency>
40+
</dependencies>
41+
</project>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.zuicoding.platform;
2+
3+
/**
4+
* Hello world!
5+
*
6+
*/
7+
public class App
8+
{
9+
public static void main( String[] args )
10+
{
11+
System.out.println( "Hello World!" );
12+
}
13+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.zuicoding.platform.mybatis.dialect;
2+
3+
/**
4+
* Created by Stephen.liln on 2017/8/31.
5+
* <p>
6+
* Description :<p></p>
7+
*/
8+
public interface IDialect {
9+
10+
String buildPaginationSql(String sql, int offset, int limit);
11+
12+
String buildCountSql(String sql);
13+
14+
/**
15+
* default implement
16+
*/
17+
public static enum DefaultDialect implements IDialect{
18+
19+
MYSQL{
20+
@Override
21+
public String buildPaginationSql(String sql, int offset, int limit) {
22+
StringBuilder limitSql = new StringBuilder(sql);
23+
limitSql.append(" LIMIT ").append(offset).append(",").append(limit);
24+
return limitSql.toString();
25+
}
26+
27+
@Override
28+
public String buildCountSql(String sql) {
29+
30+
return String.format("SELECT COUNT(1) AS TOTAL FROM(%s) AS TEMP", sql);
31+
}
32+
},
33+
ORACLE {
34+
@Override
35+
public String buildPaginationSql(String sql, int offset, int limit) {
36+
return null;
37+
}
38+
39+
@Override
40+
public String buildCountSql(String sql) {
41+
return null;
42+
}
43+
},
44+
SQLSERVER{
45+
@Override
46+
public String buildPaginationSql(String sql, int offset, int limit) {
47+
return null;
48+
}
49+
50+
@Override
51+
public String buildCountSql(String sql) {
52+
return null;
53+
}
54+
};
55+
}
56+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.zuicoding.platform.mybatis.pagination;
2+
3+
/**
4+
* Created by Stephen.lin on 2017/8/4.
5+
* <p>
6+
* Description :<p></p>
7+
*/
8+
public class Pager {
9+
10+
private int pageNum = 1;
11+
private int pageSize = 10;
12+
13+
private int offset = 0;
14+
private int total = 0;
15+
private int pageTotal = 0;
16+
17+
public Pager() {
18+
}
19+
20+
public Pager(int pageNum, int pageSize) {
21+
this.pageNum = pageNum;
22+
this.pageSize = pageSize;
23+
}
24+
25+
public Pager(int pageNum) {
26+
this.pageNum = pageNum;
27+
}
28+
29+
public int getPageNum() {
30+
return pageNum;
31+
}
32+
33+
public void setPageNum(int pageNum) {
34+
this.pageNum = pageNum;
35+
}
36+
37+
public int getPageSize() {
38+
return pageSize;
39+
}
40+
41+
public void setPageSize(int pageSize) {
42+
this.pageSize = pageSize;
43+
}
44+
45+
public int getOffset() {
46+
offset = (pageNum - 1) * pageSize;
47+
return offset;
48+
}
49+
50+
public int getTotal() {
51+
return total;
52+
}
53+
54+
public void setTotal(int total) {
55+
this.total = total;
56+
}
57+
58+
public int getPageTotal() {
59+
pageTotal = (pageTotal % pageSize ) == 0 ? pageTotal / pageSize : (pageTotal / pageSize) + 1;
60+
return pageTotal;
61+
}
62+
63+
64+
}
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
package com.zuicoding.platform.mybatis.pagination;
2+
3+
4+
import com.zuicoding.platform.mybatis.dialect.IDialect;
5+
import org.apache.ibatis.builder.StaticSqlSource;
6+
import org.apache.ibatis.executor.Executor;
7+
import org.apache.ibatis.mapping.*;
8+
import org.apache.ibatis.plugin.*;
9+
import org.apache.ibatis.session.ResultHandler;
10+
import org.apache.ibatis.session.RowBounds;
11+
import org.slf4j.Logger;
12+
import org.slf4j.LoggerFactory;
13+
14+
import java.util.ArrayList;
15+
import java.util.Collections;
16+
import java.util.List;
17+
import java.util.Properties;
18+
19+
/**
20+
* Created by Stephen.lin on 2017/8/31.
21+
* <p>
22+
* Description :<p>mybatis 分页插件</p>
23+
*/
24+
@Intercepts({
25+
@Signature(type = Executor.class,method = "query", args = { MappedStatement.class, Object.class,
26+
RowBounds.class, ResultHandler.class })
27+
})
28+
public class PaginationHandler implements Interceptor {
29+
30+
private Logger log = LoggerFactory.getLogger(PaginationHandler.class);
31+
32+
public static final ThreadLocal<Pager> localPage = new ThreadLocal<Pager>();
33+
34+
private IDialect dialect = IDialect.DefaultDialect.MYSQL;
35+
36+
private static final List<ResultMap> COUNT_RESULTMAPS = new ArrayList<>(1);
37+
38+
private static final String COUNT_SQL_SUFFIX = "-SELECT-COUNT";
39+
40+
/**
41+
* 以此方法名字结尾的查询
42+
*/
43+
private String methodSuffix = "ByPager";
44+
45+
public static void pageStart(int pageNum,int pageSize){
46+
if (pageNum <=0) pageNum = 1;
47+
localPage.set(new Pager(pageNum,pageSize));
48+
}
49+
public static void pageStart(Pager pager){
50+
if (pager == null) pager = new Pager();
51+
localPage.set(pager);
52+
}
53+
54+
public static void pageStart(){
55+
pageStart(null);
56+
}
57+
58+
public static Pager pageEnd(){
59+
Pager pager = localPage.get();
60+
localPage.remove();
61+
return pager;
62+
}
63+
64+
@Override
65+
public Object intercept(Invocation invocation) throws Throwable {
66+
MappedStatement ms = (MappedStatement) invocation.getArgs()[0];
67+
log.info("sql Command Type:{}",ms.getSqlCommandType());
68+
69+
if (ms.getSqlCommandType() != SqlCommandType.SELECT) return invocation.proceed();
70+
if (log.isDebugEnabled()){
71+
log.debug("mappedStatement id : {}",ms.getId());
72+
}
73+
if (!ms.getId().endsWith(methodSuffix)) return invocation.proceed();
74+
75+
Pager pager = localPage.get();
76+
if(pager == null){
77+
log.warn("page message is null");
78+
return invocation.proceed();
79+
}
80+
81+
Object parameter = invocation.getArgs()[1];
82+
BoundSql originSql = ms.getBoundSql(parameter);
83+
if (log.isDebugEnabled()){
84+
log.debug("origin sql is:{}",originSql.getSql());
85+
}
86+
87+
String countSql = this.dialect.buildCountSql(originSql.getSql());
88+
if (log.isDebugEnabled()){
89+
log.debug("count sql is : {}",countSql);
90+
}
91+
//有些查询不需要查询总数
92+
if (countSql != null && !"".equals(countSql.trim())){
93+
94+
if (COUNT_RESULTMAPS.size() == 0){
95+
COUNT_RESULTMAPS.add(new ResultMap.Builder(ms.getConfiguration(),
96+
ms.getId()+COUNT_SQL_SUFFIX,Integer.class,
97+
Collections.<ResultMapping>emptyList()).build());
98+
}
99+
100+
//构建 count bound sql
101+
BoundSql countBoundSql = new BoundSql(ms.getConfiguration(),
102+
countSql,originSql.getParameterMappings(),
103+
originSql.getParameterObject());
104+
105+
Executor executor = (Executor) invocation.getTarget();
106+
//构建 count MappedStatement
107+
MappedStatement countMs = reBuildMappedStatement(ms,countBoundSql,true);
108+
List<Integer> list = executor.query(countMs,parameter,RowBounds.DEFAULT,null);
109+
if (list!=null && !list.isEmpty()){
110+
int total = list.get(0);
111+
pager.setTotal(total);
112+
}
113+
114+
}
115+
116+
String limitSql = this.dialect.buildPaginationSql(originSql.getSql(),pager.getOffset(),pager.getPageSize());
117+
if(log.isDebugEnabled()){
118+
log.debug("limit sql is : {}",limitSql);
119+
}
120+
BoundSql limitBoundSql = new BoundSql(ms.getConfiguration(),
121+
limitSql,originSql.getParameterMappings(),originSql.getParameterObject());
122+
123+
MappedStatement newMs = reBuildMappedStatement(ms,limitBoundSql,false);
124+
125+
invocation.getArgs()[0] = newMs;
126+
log.info(" reBuild limit sql finished...");
127+
return invocation.proceed();
128+
}
129+
130+
/**
131+
* 构造新的MappedStatement 对象
132+
* @param ms
133+
* @param newBoundSql
134+
* @param isCount
135+
* @return
136+
*/
137+
private MappedStatement reBuildMappedStatement(MappedStatement ms,
138+
BoundSql newBoundSql,boolean isCount){
139+
String id = ms.getId();
140+
if (isCount){
141+
id += COUNT_SQL_SUFFIX;
142+
}
143+
if (log.isDebugEnabled()){
144+
log.debug("sql id is:{}",id);
145+
}
146+
MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(),
147+
id,
148+
new StaticSqlSource(ms.getConfiguration(),
149+
newBoundSql.getSql(),newBoundSql.getParameterMappings()), ms.getSqlCommandType());
150+
builder.resource(ms.getResource());
151+
builder.fetchSize(ms.getFetchSize());
152+
builder.statementType(ms.getStatementType());
153+
builder.keyGenerator(ms.getKeyGenerator());
154+
// if (ms.getKeyProperties() != null){
155+
// builder.keyProperty(StringUtils.join(ms.getKeyProperties(),","));
156+
// }
157+
builder.timeout(ms.getTimeout());
158+
builder.parameterMap(ms.getParameterMap());
159+
160+
builder.resultSetType(ms.getResultSetType());
161+
builder.cache(ms.getCache());
162+
builder.flushCacheRequired(ms.isFlushCacheRequired());
163+
builder.useCache(ms.isUseCache());
164+
builder.resultMaps(ms.getResultMaps());
165+
//如果是构建 count mappedStatement,将 查询 count result map 设置进去
166+
if (isCount){
167+
builder.resultMaps(COUNT_RESULTMAPS);
168+
169+
}
170+
171+
return builder.build();
172+
}
173+
174+
175+
@Override
176+
public Object plugin(Object target) {
177+
if (target instanceof Executor){
178+
return Plugin.wrap(target,this);
179+
}
180+
return target;
181+
}
182+
183+
@Override
184+
public void setProperties(Properties properties) {
185+
String dialectStr = properties.getProperty("dialect","mysql");
186+
if (log.isDebugEnabled()){
187+
log.debug("sql dialect is : {}",dialectStr);
188+
}
189+
try {
190+
IDialect.DefaultDialect defaultDialect = IDialect.DefaultDialect.valueOf(dialectStr);
191+
this.dialect = defaultDialect;
192+
}catch (Exception e){
193+
log.warn("No enum from default dialect:"+dialectStr);
194+
try {
195+
this.dialect = (IDialect)Class.forName(dialectStr).newInstance();
196+
}catch (Exception e1){
197+
throw new IllegalArgumentException(e1);
198+
}
199+
}
200+
201+
this.methodSuffix = properties.getProperty("methodSuffix",this.methodSuffix);
202+
203+
log.info(" init properties finished, dialect value is : {},methodSuffix",dialect,methodSuffix);
204+
}
205+
206+
public IDialect getDialect() {
207+
return dialect;
208+
}
209+
210+
public void setDialect(IDialect dialect) {
211+
this.dialect = dialect;
212+
}
213+
214+
}

0 commit comments

Comments
 (0)