一 方言


mybatis.pagination.dialect.Dialect.java
1
2
3
4
5
6
7
8
package  mybatis.pagination.dialect;
 
/**
  * Created by Administrator on 2015/4/29.
  */
public  interface  Dialect {
     public  String getLimitString(String sql,  int  offset,  int  limit);
}
mybatis.pagination.dialect.MySqlDialect.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package  mybatis.pagination.dialect;
  
/**
  * Created by Administrator on 2015/4/29.
  */
public  class  MySqlDialect  implements  Dialect{
  
     @Override
     public  String getLimitString(String sql,  int  offset,  int  limit) {
         String newSql =  "select * from (" +sql+ ") e limit " +offset+ "," +limit;
  
         return  newSql;
     }
}

mybatis.pagination.dialect.DialectProvider.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package  mybatis.pagination.dialect;
 
/**
  * Created by Administrator on 2015/4/29.
  */
public  class  DialectProvider {
     private  static  DialectProvider dialectProvider =  new  DialectProvider();
 
     private  DialectProvider(){}
 
     public  static  DialectProvider getInstance(){
         return  dialectProvider;
     }
 
     public  Dialect getDialect(String dialectName){
         if ( "mysql" .equals(dialectName)){
             return  new  MySqlDialect();
         }
         throw  new  RuntimeException( "can't find the specified dialect : " +dialectName);
     }
 
 
}


二 分页拦截器 

mybatis.pagination.interceptor.PaginationInterceptor.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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
81
82
83
package  mybatis.pagination.interceptor;
 
import  mybatis.pagination.dialect.Dialect;
import  mybatis.pagination.dialect.DialectProvider;
import  org.apache.ibatis.executor.statement.StatementHandler;
import  org.apache.ibatis.mapping.BoundSql;
import  org.apache.ibatis.plugin.*;
import  org.apache.ibatis.reflection.MetaObject;
import  org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import  org.apache.ibatis.reflection.factory.ObjectFactory;
import  org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import  org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import  org.apache.ibatis.session.Configuration;
import  org.apache.ibatis.session.RowBounds;
 
import  java.sql.Connection;
import  java.util.Properties;
 
/**
  * 通过拦截<code>StatementHandler</code>的<code>prepare</code>方法,重写sql语句实现物理分页。
  * 老规矩,签名里要拦截的类型只能是接口。
  *
  */
@Intercepts ({ @Signature (type = StatementHandler. class , method =  "prepare" , args = {Connection. class })})
public  class  PaginationInterceptor  implements  Interceptor {
     private  static  final  ObjectFactory DEFAULT_OBJECT_FACTORY =  new  DefaultObjectFactory();
     private  static  final  ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY =  new  DefaultObjectWrapperFactory();
 
     @Override
     public  Object intercept(Invocation invocation)  throws  Throwable {
         StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
         MetaObject metaStatementHandler = MetaObject.forObject(statementHandler, DEFAULT_OBJECT_FACTORY,DEFAULT_OBJECT_WRAPPER_FACTORY);
         RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue( "delegate.rowBounds" );
 
         // property在mybatis settings文件内配置
         Configuration configuration = (Configuration) metaStatementHandler.getValue( "delegate.configuration" );
 
         // 只重写需要分页的sql语句。通过MappedStatement的ID匹配,默认重写以Page结尾的MappedStatement的sql
         BoundSql boundSql = (BoundSql) metaStatementHandler.getValue( "delegate.boundSql" );
 
         String sql = boundSql.getSql();
         // 重写sql
         Dialect dialect = getDialect(configuration);
         String newSql = dialect.getLimitString(sql,rowBounds.getOffset(),rowBounds.getLimit());
         metaStatementHandler.setValue( "delegate.boundSql.sql" , newSql);
 
         // 采用物理分页后,就不需要mybatis的内存分页了,所以重置下面的两个参数
         metaStatementHandler.setValue( "delegate.rowBounds.offset" , RowBounds.NO_ROW_OFFSET);
         metaStatementHandler.setValue( "delegate.rowBounds.limit" , RowBounds.NO_ROW_LIMIT);
         // 将执行权交给下一个拦截器
         return  invocation.proceed();
     }
 
     private  Dialect getDialect(Configuration configuration){
         Properties properties = configuration.getVariables();
 
         if (properties== null ){
             properties =  new  Properties();
         }
 
         String dialectName = properties.getProperty( "dialect" , "mysql" );
 
         return  DialectProvider.getInstance().getDialect(dialectName);
     }
 
     @Override
     public  Object plugin(Object target) {
         // 当目标类是StatementHandler类型时,才包装目标类,否者直接返回目标本身,减少目标被代理的次数
         if  (target  instanceof  StatementHandler) {
             return  Plugin.wrap(target,  this );
         else  {
             return  target;
         }
     }
 
     @Override
     public  void  setProperties(Properties properties) {
         //To change body of implemented methods use File | Settings | File Templates.
     }
 
 
 
}


 三 Mybatis 配置

1
2
3
< properties >
     < property  name = "dialect"  value = "mysql" />
</ properties >
1
2
3
< plugins >
     < plugin  interceptor = "mybatis.pagination.interceptor.PaginationInterceptor" />
</ plugins >


四 pom.xml

1
2
3
4
5
< dependency >
     < groupId >org.mybatis</ groupId >
     < artifactId >mybatis</ artifactId >
     < version >3.1.1</ version >
</ dependency >