Mybatis的自带分页方法只是逻辑分页,如果数据量很大,内存会溢出,不知道为什么开源组织不在里面实现类似Hibernate的物理分页处理方法。在不改动Mybatis源代码的情况下,怎么使Mybatis支持物理分页呢?下面我们来看看。
(1)新建一个Java类Dialect.java,该类的内容如下:
- package org.mybatis.extend.interceptor;
-
- public abstract class Dialect {
-
- public static enum Type{
- MYSQL,
- ORACLE
- }
-
- public abstract String getLimitString(String sql, int skipResults, int maxResults);
-
- }
(2)新建一个Java类OracleDialect.java,该类继承Dialect 类,具体的内容如下:
- package org.mybatis.extend.interceptor;
-
- public class OracleDialect extends Dialect{
-
-
-
-
- @Override
- public String getLimitString(String sql, int offset, int limit) {
-
- sql = sql.trim();
- StringBuffer pagingSelect = new StringBuffer(sql.length() + 100);
-
- pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
-
- pagingSelect.append(sql);
-
- pagingSelect.append(" ) row_ ) where rownum_ > ").append(offset).append(" and rownum_ <= ").append(offset + limit);
-
- return pagingSelect.toString();
- }
-
- }
(3)新建一个Mybaits的拦截器PaginationInterceptor.java,实现Interceptor接口,该类的内容如下:
- package org.mybatis.extend.interceptor;
-
- import java.sql.Connection;
- import java.util.Map;
- import java.util.Properties;
-
- import org.apache.ibatis.executor.parameter.DefaultParameterHandler;
- import org.apache.ibatis.executor.statement.StatementHandler;
- import org.apache.ibatis.mapping.BoundSql;
- import org.apache.ibatis.plugin.Interceptor;
- import org.apache.ibatis.plugin.Intercepts;
- import org.apache.ibatis.plugin.Invocation;
- import org.apache.ibatis.plugin.Plugin;
- import org.apache.ibatis.plugin.Signature;
- import org.apache.ibatis.reflection.MetaObject;
- import org.apache.ibatis.session.Configuration;
- import org.apache.ibatis.session.RowBounds;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
-
-
- @Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class})})
- public class PaginationInterceptor implements Interceptor {
-
- protected static Logger log = LoggerFactory.getLogger(PaginationInterceptor.class);
-
-
-
- @Override
- public Object intercept(Invocation invocation) throws Throwable {
- StatementHandler statementHandler = (StatementHandler)invocation.getTarget();
- MetaObject metaStatementHandler = MetaObject.forObject(statementHandler);
-
- RowBounds rowBounds = (RowBounds)metaStatementHandler.getValue("delegate.rowBounds");
- if(rowBounds == null || rowBounds == RowBounds.DEFAULT){
- return invocation.proceed();
- }
-
- DefaultParameterHandler defaultParameterHandler = (DefaultParameterHandler)metaStatementHandler.getValue("delegate.parameterHandler");
- Map parameterMap = (Map)defaultParameterHandler.getParameterObject();
- Object sidx = parameterMap.get("_sidx");
- Object sord = parameterMap.get("_sord");
-
- String originalSql = (String)metaStatementHandler.getValue("delegate.boundSql.sql");
-
- if(sidx != null && sord != null){
- originalSql = originalSql + " order by " + sidx + " " + sord;
- }
-
- Configuration configuration = (Configuration)metaStatementHandler.getValue("delegate.configuration");
-
- Dialect.Type databaseType = null;
- try{
- databaseType = Dialect.Type.valueOf(configuration.getVariables().getProperty("dialect").toUpperCase());
- } catch(Exception e){
-
- }
- if(databaseType == null){
- throw new RuntimeException("the value of the dialect property in configuration.xml is not defined : " + configuration.getVariables().getProperty("dialect"));
- }
- Dialect dialect = null;
- switch(databaseType){
- case ORACLE:
- dialect = new OracleDialect();
- break;
- case MYSQL:
- break;
-
- }
-
-
- metaStatementHandler.setValue("delegate.boundSql.sql", dialect.getLimitString(originalSql, rowBounds.getOffset(), rowBounds.getLimit()) );
- metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET );
- metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT );
- if(log.isDebugEnabled()){
- BoundSql boundSql = statementHandler.getBoundSql();
- log.debug("生成分页SQL : " + boundSql.getSql());
- }
- return invocation.proceed();
- }
-
-
-
-
- @Override
- public Object plugin(Object target) {
- return Plugin.wrap(target, this);
- }
-
-
-
-
- @Override
- public void setProperties(Properties arg0) {
-
-
- }
-
- }
(4)将Mybatis的拦截器配置到Mybatis的全局配置文件(mybatis.cfg.xml)中,具体如下:
- <?xml version="1.0" encoding="UTF-8" ?>
-
- <!DOCTYPE configuration PUBLIC
- "-//mybatis.org//DTD Config 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-config.dtd">
-
- <configuration>
- <properties>
- <property name="dialect" value="oracle"/>
- </properties>
-
- <plugins>
- <plugin interceptor="org.mybatis.extend.interceptor.PaginationInterceptor"/>
- </plugins>
-
- </configuration>
(5)使用方法同Mybatis逻辑分页一样,拦截器会自动拦截执行SQL的地方,加上分页代码:
- getSqlSession().selectList(sqlId, paramMap,new RowBounds(pageId, pageSize));
分享到:
相关推荐
而“mybatis物理分页插件”是针对MyBatis设计的一个扩展,用于解决在大数据量查询时的性能问题,通过实现物理分页来避免内存溢出。 物理分页是指在数据库层面进行分页,相比于逻辑分页(在应用层进行数据截取),...
总结来说,`mybatis-paginator`是一个强大且实用的工具,它帮助开发者在MyBatis中轻松实现物理分页,提高大数据查询的效率。通过学习和使用这个插件,你可以更深入地理解数据库分页原理,并提升你的项目性能。同时,...
本主题将深入探讨Mybatis3中如何实现物理分页,特别是通过拦截器来实现这一功能。 首先,我们来看Interceptor接口。在Mybatis中,拦截器扮演着关键角色,它允许我们在特定的执行点(如SQL语句的准备、执行等)插入...
通用Mapper通过动态代理技术实现了方法的自动映射,只需要定义Mapper接口,无需编写XML,即可实现对数据库的基本操作。 PageHelper是另一个MyBatis的分页插件,它提供了强大的分页功能,可以无缝地与MyBatis和...
在MySQL中,我们通常使用LIMIT和OFFSET关键字来实现物理分页,LIMIT用于指定每页显示的记录数,OFFSET则用来偏移起始位置。 在MyBatis中实现分页,我们需要以下步骤: 1. **配置MyBatis**:确保你的项目已经集成了...
综上所述,修改Ibatis源代码实现物理分页涉及的关键技术包括动态SQL、自定义插件、数据库方言处理以及性能优化。通过这样的改造,我们可以充分利用数据库的分页功能,提高查询效率,降低内存占用,从而提升整个系统...
MyBatis的分页功能通常通过PageHelper或MyBatis-Plus等插件实现,它们允许开发者在不修改原有SQL的基础上,轻松实现物理分页或逻辑分页。分页不仅可以提高应用的性能,避免一次性加载大量数据导致内存压力,还能提供...
PageHelper通过拦截器的方式,自动拦截SQL,实现物理分页。使用PageHelper后,只需要在Mapper接口的方法上添加@Select、@Insert、@Update或@Delete注解,就可以自动实现分页功能,极大地提高了开发效率。 【BaseDao...
只需在查询方法上添加PageHelper.startPage()和 PageInfo.Page(),即可实现物理分页,同时支持多种数据库,如MySQL、Oracle等。 6. **配置PageHelper**:在Spring配置文件中,需要引入PageHelper的bean,配置数据库...
5. **物理分页**:通过数据库特有的分页机制实现物理分页,提高查询效率。 6. **逻辑分页**:在某些不支持物理分页的数据库中,通过排序和限制数据量实现逻辑分页。 7. **动态SQL生成**:根据分页参数动态生成高效的...
Spring整合Mybatis是Java开发中常见的一种技术组合,它将Spring的IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)能力与Mybatis的灵活SQL映射功能结合,提高了开发效率并...
PageHelper不仅支持物理分页,还支持逻辑分页,同时兼容多种数据库,如MySQL、Oracle、DB2等。 在"描述"中提到,这是一个新手项目,后端已经测试正常,这意味着分页功能已经在服务器端实现了。然而,前端网页部分...
12. **内置分页插件**:基于MyBatis物理分页机制,简化了分页查询的实现。 13. **性能分析插件**:可以输出SQL语句及其执行时间,帮助开发人员优化慢查询。 14. **全局拦截插件**:提供全表DELETE/UPDATE操作的智能...
- **PageHelper分页插件**:这是一个非常实用的Mybatis分页插件,它可以实现物理分页和逻辑分页,只需简单配置即可实现高效、便捷的分页功能。 - **Mybatis-Plus**:它是Mybatis的增强工具,在Mybatis的基础上只做...
【标签】中的"pagehelper"是我们的主要讨论对象,它是一个广泛使用的MyBatis插件,提供了包括物理分页、逻辑分页、参数处理、结果处理等功能。"分页插件"强调了PageHelper的核心作用,即实现高效且易于使用的数据库...
使用PageHelper可以简化分页查询的编写,提高开发效率,同时提供了一套完整的解决方案,包括物理分页、逻辑分页、参数处理等。 5. **Junit4**:JUnit4是Java领域广泛使用的单元测试框架,它提供了丰富的断言方法和...
Android+Java后端(Springboot+Mybatis)小商店项目源码+数据库+项目说明.zip 主要实现一个商城的下单、购物车、支付等基本功能,熟悉后端的开发过程,因为自己做...PageHelper MyBatis物理分页插件 Redis 分布式缓存
【PageHelper】是MyBatis的分页插件,它对MyBatis的SQL执行过程进行了拦截,实现了物理分页。PageHelper提供了强大的分页功能,可以自动计算总页数、总记录数,支持多种数据库,如MySQL、Oracle等,并且能自动识别...
- **内置分页插件**:支持物理分页,使用简单直观,适用于多种数据库。 - **性能分析插件**:可输出SQL语句及其执行时间,有助于开发者在开发测试阶段迅速定位性能瓶颈。 - **全局拦截插件**:提供全表delete、...
在分页功能上,Mybatis-Plus内置了PageHelper插件,可以实现高效的物理分页,同时兼容各种数据库,如MySQL、Oracle等。开发者只需要简单设置即可实现优雅的分页效果。 另外,Mybatis-Plus3.0还提供了丰富的扩展点,...