一 方言
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