mybatis的SqlSession可以直接通过以下接口来进行分页查询:
<E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);
不过该查询是基于对查询结果去子集的方式。该方法效率较低(如果只查询一条数据服务器需要返回所有满足条件的数据)。
实现思路:用mybatis插件拦截StatementHandler的prepare方法,修改Sql语句,添加分页查询语句。至于分页中的总页数查询,另执行一条select count(*)查询语句。实现较简单。
StatementHandler 的执行过程简介:
在Executor中通过下面代码创建StatementHandler:
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
configuration是mybatis的全局配置文件,其newStatementHandler创建过程如下:
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql); statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler); return statementHandler; }
RoutingStatementHandler可以看作是非法语句处理器,具体的操作还是要委托给具体的BaseStatementHandler。interceptorChain.pluginAll用于将所有配置的myabtis插件类应用到这个接口上面。interceptorChain是一个拦截器链(职责链模式)
public Object pluginAll(Object target) { for (Interceptor interceptor : interceptors) { target = interceptor.plugin(target); } return target; }
interceptors保存着配置mybatis的所有拦截器,分别调用拦截器对目标进行代理。也就是生成目标类的代理。例如拦截器Incet
package cn.liuyao.mybatis.test; import java.util.Properties; import org.apache.ibatis.executor.statement.StatementHandler; 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; @Intercepts({@Signature(type = StatementHandler.class,method = "prepare",args = {java.sql.Connection.class})}) public class Incet implements Interceptor{ @Override public Object intercept(Invocation invocation) throws Throwable { return invocation.proceed(); } //生成目标对象的代理 @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { } }
拦截器的plugin方法调用Plugin的wrap对目标对象包装代理。
public static Object wrap(Object target, Interceptor interceptor) { Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor); Class<?> type = target.getClass(); Class<?>[] interfaces = getAllInterfaces(type, signatureMap); if (interfaces.length > 0) { return Proxy.newProxyInstance( type.getClassLoader(), interfaces, new Plugin(target, interceptor, signatureMap)); } return target; }
wrap返回目标对象的代理,这样在执行特定接口的特定方法时候,能够增加自己的一些代码,类似于spring的aop功能。
Object intercept(Invocation invocation)
intercept编写额外的代码。实现自己的分页逻辑。
由于mybatis的语句执行,最终都由StatementHandler来完成,故只要拦截该接口的prepare方法,并修改boundSql与rowBound既可以达到修改Sql与添加分页信息的效果。
Page类:
package com.ccq.framework.lang; import java.io.Serializable; public class Page implements Serializable{ private static final long serialVersionUID = 9000151198919642793L; private int pages; private int pageNum; private int pageSize; public Page() { super(); // TODO Auto-generated constructor stub } public Page(int pages, int pageNum, int pageSize) { super(); this.pages = pages; this.pageNum = pageNum; this.pageSize = pageSize; } public int getPages() { return pages; } public void setPages(int pages) { this.pages = pages; } public int getPageNum() { return pageNum; } public void setPageNum(int pageNum) { this.pageNum = pageNum; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } }page类用于保存分页信息:当前页,页大小,所有页数。
pagePlugin:
package com.ccq.framework.plugin; import java.util.Properties; 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.DefaultReflectorFactory; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.factory.DefaultObjectFactory; import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory; import org.apache.ibatis.session.RowBounds; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Intercepts({@Signature(type = StatementHandler.class,method = "prepare",args = {java.sql.Connection.class})}) public class MyPagePlugin implements Interceptor{ private Dialect dialect; @Override public Object intercept(Invocation invocation) throws Throwable { Logger log = LoggerFactory.getLogger(MyPagePlugin.class); StatementHandler hander = (StatementHandler) invocation.getTarget(); //对handler进行包装可以获取其私有属性 MetaObject meta = MetaObject.forObject(hander, new DefaultObjectFactory(), new DefaultObjectWrapperFactory(), new DefaultReflectorFactory()); RowBounds rowBound = (RowBounds) meta.getValue("delegate.rowBounds");//获取分页信息 if(rowBound.equals(RowBounds.DEFAULT)) { //未指定分页命令 return invocation.proceed(); } BoundSql boundSql = (BoundSql) meta.getValue("delegate.boundSql");//获取sql语句 if(dialect == null) { log.debug("not assigned dialect,use mysql default"); dialect = new MysqlDialect(); } String buildSql = dialect.builderSql(boundSql.getSql(), rowBound.getOffset(), rowBound.getLimit()); MetaObject boundSqlMeta = MetaObject.forObject(boundSql, new DefaultObjectFactory(), new DefaultObjectWrapperFactory(), new DefaultReflectorFactory()); boundSqlMeta.setValue("sql", buildSql); meta.setValue("delegate.rowBounds", RowBound.DEFAULT);//回复默认的分页信息 return invocation.proceed(); } //生成目标对象的代理 @Override public Object plugin(Object target) { if(target instanceof StatementHandler) { return Plugin.wrap(target, this); }else { return target; } } @Override public void setProperties(Properties properties) { if(properties.getProperty("dialect").equals("mysql")) { dialect = new MysqlDialect(); }else if(properties.getProperty("dialect").equals("oracle")) { //TODO } } }buildSql:
package com.ccq.framework.plugin; import com.ccq.framework.exception.AppException; public class MysqlDialect extends Dialect{ @Override public String builderSql(String rawSql,int OFFSET,int LIMIT) { if(rawSql.endsWith(";")) { throw new AppException("Bad sql: grammer error on ; with limit"); } StringBuffer sb = new StringBuffer(rawSql); //SELECT * FROM table LIMIT [offset,] rows sb.append(String.format(" limit %s,%s",new Object[]{OFFSET,LIMIT})); return sb.toString(); } }
只针对mysql的sql语句。
测试:采用了的mybatis的通用单表CRUD工具,后面给链接。
相关推荐
06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo06实现mybatis分页插件demo...
而“mybatis物理分页插件”是针对MyBatis设计的一个扩展,用于解决在大数据量查询时的性能问题,通过实现物理分页来避免内存溢出。 物理分页是指在数据库层面进行分页,相比于逻辑分页(在应用层进行数据截取),...
Mybatis通用分页插件是Java开发中广泛使用的ORM(对象关系映射)框架扩展,主要针对Mybatis进行优化,提供了高效便捷的分页功能。这个插件的目的是简化在数据库查询时的分页操作,使得开发者能够更专注于业务逻辑,...
【标题】"mybatis分页插件代码"主要涉及到MyBatis框架中的一种增强功能——分页插件的使用。MyBatis是一个优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。在处理大数据量时,分页查询是必不可少的优化...
本教程将详细讲解如何在Spring Boot项目中集成MyBatis,并利用分页插件实现高效的数据分页。 首先,我们需要在Spring Boot项目中引入MyBatis依赖。在`pom.xml`文件中添加以下Maven依赖: ```xml <groupId>org....
MyBatis 分页插件是针对 MyBatis 框架设计的一款强大的辅助工具,它极大地简化了在数据库查询时的分页操作。在没有分页插件的情况下,开发者需要手动编写分页相关的 SQL 语句,这既繁琐又容易出错。而 PageHelper ...
本文将详细介绍如何在 MyBatis 中实现自定义分页插件。 自定义分页插件提供了一种灵活且高效的方式来实现 MyBatis 的分页查询。通过实现 Interceptor 接口并注册插件,我们可以根据不同的业务需求和数据库特性来定制...
mybatis集成了分页的插件,采用springmvc+spring+mybatis或者springboot+mybatis的时候可以无缝对接使用
mybatis分页插件支持查询~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
NULL 博文链接:https://hzs0502030128.iteye.com/blog/2254585
在本文中,我们将深入探讨如何使用JSP、Servlet和MyBatis这三种技术来实现一个分页查询的功能。这是一个常见的需求,在许多Web应用程序中,为了提高用户体验,通常需要将大量数据分批次展示,而不是一次性加载所有...
### Mybatis分页插件详解 #### 一、概述 在使用Mybatis处理大量数据时,分页查询是一项常见的需求。传统的做法是在SQL语句中手动加入`LIMIT`和`OFFSET`来实现分页功能,这种方法不仅繁琐而且容易出错。针对这一...
MyBatis分页插件是数据库操作中常用的一种工具,它可以帮助开发者在使用MyBatis框架进行数据查询时实现高效且便捷的分页功能。在Java Web开发中,当需要处理大量的数据时,分页显示不仅可以提高用户体验,也能减轻...
myBatis自动分页插件PageHelper5.0,支持自动分页,很方便,内含两个java包,分别是:PageHelper5.0.1.jar;jsqlparser-0.9.4.jar(PageHelper 4.1.0 及以后版本需要此包支持)
在本篇中,我们将深入探讨如何在Spring Boot项目中集成MyBatis分页插件,以便为数据库查询提供高效、便捷的分页功能。Spring Boot以其简洁的配置和快速的开发体验深受开发者喜爱,而MyBatis作为轻量级持久层框架,与...
分页插件PageHelper是通过mybatis的拦截器实现分页功能的,拦截sql查询请求,添加分页语句,最终实现分页查询功能。 一、分页插件PageHelper支持的数据库类型? Oracle,MySql,MariaDB,SQLite等 二、分页插件...
下面我们将深入探讨MyBatis分页插件的相关知识点。 1. **MyBatis框架基础** MyBatis是一个优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果...
自己最近搭建的一个SpringMVC+Mybatis的框架 属于无实体类的框架 并实现了Myabtis的自动分页和总数查询 只要传入分页参数便能自动查询总数和分页 总数封装在参数里面执行查询后可以直接从参数中获取