Mybatis 物理分页

一 方言


mybatis.pagination.dialect.Dialect.java
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
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

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
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 配置

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


四 pom.xml

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.1.1</version>
</dependency>


你可能感兴趣的:(java,Web,mybatis,pagination)