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>
时间: 2024-10-08 19:55:55

Mybatis 物理分页的相关文章

MyBatis物理分页的代码实现

一.分页 MyBatis有两种分页方法:内存分页,也就是假分页,本质是查出所有的数据然后根据游标的方式,截取需要的记录,如果数据量大,执行效率低,可能造成内存溢出.物理分页,就是数据库本身提供了分页方式,如MySql的limit,执行效率高,不同数据库实现不同. MyBatis Generator使用:MyBatis Generator使用示例 Spring集成MyBatis:Spring集成MyBatis持久层框架 二.MyBatis执行流程 MyBatis执行sql流程如下图,实现数据库的物

spring+mybatis 物理分页

新项目用的spring mvc 和 mybatis 分页.研究了一下,集众家之长然后形成现在的项目.我把分页部分剥离出来与大家分享.如有不妥的地方欢迎交流拍砖. 单独做了一个小项目,放到了下载区,如果有用到的朋友可以去下载. 本项目采用了拦截器,就是mybaits自带的plus功能.将每次select操作都进行拦截. 项目架构如下: 1:首先从cotroller层出发,啥也不说,上代码.这个最实惠 package com.flydreamer.controller; import java.ut

MyBatis 物理分页foreach 参数失效

MyBatis-3.4.4.jar使用分页插件时并且查询条件包含foreach时,分页插件在执行count语句时会抛出异常,报参数为空异常.分页插件会新增一个COUNT的SQL,并复制原BoundSql对象,然后使用DefaultParameterHandler.setParameters给COUNT语句设值.foreach过程中产生的参数变量是放在AdditionalParameter中,但复制BoundSql时并没有复制其中的additionalParameters字段,而由foreach产

mybatis实战教程(mybatis in action),mybatis入门到精通

转自:http://www.yihaomen.com/article/java/302.htm (读者注:其实这个应该叫做很基础的入门一下下,如果你看过hibernate了那这个就非常的简单) (再加一条,其实大家可以看官方的教程更好些:http://mybatis.github.io/mybatis-3/,而且如果英文不是很好的那就看中文的:http://mybatis.github.io/mybatis-3/zh/sqlmap-xml.html) 写在这个系列前面的话: 以前曾经用过ibat

mybatis实战教程(mybatis in action),mybatis入门到精通(转)

转自:http://www.yihaomen.com/article/java/302.htm (读者注:其实这个应该叫做很基础的入门一下下,如果你看过Hibernate了那这个就非常的简单) (再加一条,其实大家可以看官方的教程更好些:http://mybatis.github.io/mybatis-3/,而且如果英文不是很好的那就看中文的:http://mybatis.github.io/mybatis-3/zh/sqlmap-xml.html) 写在这个系列前面的话: 以前曾经用过ibat

关于struts2的过滤器和mybatis的插件的分析

网上一搜,发现一篇写的非常棒的博文,就直接复制过来了,供以后复习使用. 前辈博文链接:共三篇: http://jimgreat.iteye.com/blog/1616671: http://jimgreat.iteye.com/blog/1594981: http://jimgreat.iteye.com/blog/1594982: 以下为第一篇: 其实无论是AOP.拦截器还是Plugin 都是通过对目标点,一般来说就是对函数的拦截,扩展原有的功能,增加切面逻辑(日志,权限验证),修改上下文运行

【入门详解】MyBatis入门基础详解

什么是mybatis? MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyBatis使用简单的XML或注解用于配置和原始映射,将接口和Java的POJOs(Plan Old Java Objects,普通的Java对象)映射成数据库中的记录. orm工具的基本思想无论是用过的hibernate,mybatis,你都可以法相他们有一个共同点:1. 从配置文件(通常是XML配置文件中)得到 sess

mybatis学习记录

转自:http://www.yihaomen.com/article/java/302.htm (读者注:其实这个应该叫做很基础的入门一下下,如果你看过Hibernate了那这个就非常的简单) (再加一条,其实大家可以看官方的教程更好些:http://mybatis.github.io/mybatis-3/,而且如果英文不是很好的那就看中文的:http://mybatis.github.io/mybatis-3/zh/sqlmap-xml.html) 写在这个系列前面的话: 以前曾经用过ibat

Mybatis笔记

1.ibatis是mybatis的前身. 2.mybatis比hibernate灵活,性能也比hibernate好,而且也比较轻量级. 3.什么是mybatis: MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架. MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索. MyBatis使用简单的XML或注解用于配置和原始映射, 将接口和Java的POJOs(Plan Old Java Objects,普通的Java对象) 映射成 数据库中的记录. 4.