mybatis下的分页,支持所有的数据库
大家都知道,mybatis的自带分页方法只是逻辑分 页,如果数据量很大,内存一定会溢出,不知道为什么开源组织不在里面集成hibernate的物理分页处理方法!在不修改mybatis源代码的情况下, 应该怎么使mybatis支持物理分页呢?参考了网上的一些信息,有了下面的解决方法:以oracle为例子
1.把hibernate下的dialect包全部拷贝到mybatis包的jdbc目录下,如下图所示:
2.定义一个ResultSetHandler Interceptor
package cn.machi.utils;
import java.sql.Statement;
import java.util.Properties;
import org.apache.ibatis.executor.resultset.FastResultSetHandler;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
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.session.RowBounds;
@Intercepts( {@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})})
public class DiclectResultSetHandlerInterceptor implements Interceptor
{
public Object intercept(Invocation invocation) throws Throwable
{
FastResultSetHandler resultSet = (FastResultSetHandler)invocation.getTarget();
RowBounds rowBounds = (RowBounds)ReflectUtil.getFieldValue(resultSet,
"rowBounds");
if (rowBounds.getLimit() > 0
&& rowBounds.getLimit() < RowBounds.NO_ROW_LIMIT)
{
ReflectUtil.setFieldValue(resultSet, "rowBounds", new RowBounds());
}
return invocation.proceed();
}
public Object plugin(Object target)
{
return Plugin.wrap(target, this);
}
public void setProperties(Properties properties)
{
}
}
3.定义一个StatementHandler的Interceptor
package cn.machi.utils;
import java.sql.Connection;
import java.util.Properties;
import org.apache.ibatis.executor.statement.PreparedStatementHandler;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.jdbc.dialect.OracleDialect;
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.session.RowBounds;
@Intercepts( {@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class})})
public class DiclectStatementHandlerInterceptor implements Interceptor
{
private static final String DIALECT = "org.apache.ibatis.jdbc.dialect.OracleDialect";
public Object intercept(Invocation invocation) throws Throwable
{
RoutingStatementHandler statement = (RoutingStatementHandler)invocation.getTarget();
PreparedStatementHandler handler = (PreparedStatementHandler)ReflectUtil.getFieldValue(statement,
"delegate");
RowBounds rowBounds = (RowBounds)ReflectUtil.getFieldValue(handler,
"rowBounds");
if (rowBounds.getLimit() > 0
&& rowBounds.getLimit() < RowBounds.NO_ROW_LIMIT)
{
BoundSql boundSql = statement.getBoundSql();
String sql = boundSql.getSql();
OracleDialect dialect = (OracleDialect)Class.forName(DIALECT)
.newInstance();
sql = dialect.getLimitString(sql,
rowBounds.getOffset(),
rowBounds.getLimit());
ReflectUtil.setFieldValue(boundSql, "sql", sql);
}
return invocation.proceed();
}
public Object plugin(Object target)
{
return Plugin.wrap(target, this);
}
public void setProperties(Properties properties)
{
}
}
4.定义工具类ReflectUtil
package cn.machi.utils;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.apache.log4j.Logger;
public class ReflectUtil
{
private static Logger log = Logger.getLogger(ReflectUtil.class);
private static Object operate(Object obj, String fieldName,
Object fieldVal, String type)
{
Object ret = null;
try
{
// 获得对象类型
Class<? extends Object> classType = obj.getClass();
// 获得对象的所有属性
Field fields[] = classType.getDeclaredFields();
for (int i = 0; i < fields.length; i++)
{
Field field = fields[i];
if (field.getName().equals(fieldName))
{
String firstLetter = fieldName.substring(0, 1)
.toUpperCase(); // 获得和属性对应的getXXX()方法的名字
if ("set".equals(type))
{
String setMethodName = "set" + firstLetter
+ fieldName.substring(1); // 获得和属性对应的getXXX()方法
Method setMethod = classType.getMethod(setMethodName,
new Class[] {field.getType()}); // 调用原对象的getXXX()方法
ret = setMethod.invoke(obj, new Object[] {fieldVal});
}
if ("get".equals(type))
{
String getMethodName = "get" + firstLetter
+ fieldName.substring(1); // 获得和属性对应的setXXX()方法的名字
Method getMethod = classType.getMethod(getMethodName,
new Class[] {});
ret = getMethod.invoke(obj, new Object[] {});
}
return ret;
}
}
}
catch (Exception e)
{
log.warn("reflect error:" + fieldName, e);
}
return ret;
}
public static Object getVal(Object obj, String fieldName)
{
return operate(obj, fieldName, null, "get");
}
public static void setVal(Object obj, String fieldName, Object fieldVal)
{
operate(obj, fieldName, fieldVal, "set");
}
private static Method getDeclaredMethod(Object object, String methodName,
Class<?>[] parameterTypes)
{
for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass())
{
try
{
//superClass.getMethod(methodName, parameterTypes);
return superClass.getDeclaredMethod(methodName, parameterTypes);
}
catch (NoSuchMethodException e)
{
//Method 不在当前类定义, 继续向上转型
}
}
return null;
}
private static void makeAccessible(Field field)
{
if (!Modifier.isPublic(field.getModifiers()))
{
field.setAccessible(true);
}
}
private static Field getDeclaredField(Object object, String filedName)
{
for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass())
{
try
{
return superClass.getDeclaredField(filedName);
}
catch (NoSuchFieldException e)
{
//Field 不在当前类定义, 继续向上转型
}
}
return null;
}
public static Object invokeMethod(Object object, String methodName,
Class<?>[] parameterTypes, Object[] parameters)
throws InvocationTargetException
{
Method method = getDeclaredMethod(object, methodName, parameterTypes);
if (method == null)
{
throw new IllegalArgumentException("Could not find method ["
+ methodName + "] on target [" + object + "]");
}
method.setAccessible(true);
try
{
return method.invoke(object, parameters);
}
catch (IllegalAccessException e)
{
}
return null;
}
public static void setFieldValue(Object object, String fieldName,
Object value)
{
Field field = getDeclaredField(object, fieldName);
if (field == null)
throw new IllegalArgumentException("Could not find field ["
+ fieldName + "] on target [" + object + "]");
makeAccessible(field);
try
{
field.set(object, value);
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
public static Object getFieldValue(Object object, String fieldName)
{
Field field = getDeclaredField(object, fieldName);
if (field == null)
throw new IllegalArgumentException("Could not find field ["
+ fieldName + "] on target [" + object + "]");
makeAccessible(field);
Object result = null;
try
{
result = field.get(object);
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
return result;
}
}
5.更新mapper configuration文件,添加如下几条,注意plugins在整个configuration文件中的顺序
<plugins>
<plugin interceptor="functionPoint.db.DiclectStatementHandlerInterceptor"/>
<plugin interceptor="functionPoint.db.DiclectResultSetHandlerInterceptor"/>
</plugins>
6.使用方法同mybatis逻辑分页,拦截器会自动拦截执行SQL的地方,加上分页代码:
getSqlSession().selectList(mapId, queryKey,new RowBounds(pageId, pageSize));
mybatis下的分页,支持所有的数据库的更多相关文章
- jDialects:一个从Hibernate抽取的支持70多种数据库方言的原生SQL分页工具
jDialects(https://git.oschina.net/drinkjava2/jdialects) 是一个收集了大多数已知数据库方言的Java小项目,通常可用来创建分页SQL和建表DDL语 ...
- Mybatis下collections使用pageHelper进行分页
pageHelper在对mybatis一对多分页时造成查询总页数结果不对的情况. 可以做出如下修改: service层: public CommonResult worksList(String us ...
- Mybatis: 插件及分页
Mybatis采用责任链模式,通过动态代理组织多个拦截器(插件),通过这些拦截器可以改变Mybatis的默认行为(诸如SQL重写之类的). Mybatis支持对Executor.StatementHa ...
- 小书MybatisPlus第4篇-表格分页与下拉分页查询
本文为mybatis系列文档的第4篇,前三篇请访问下面的网址. 小书MybatisPlus第1篇-整合SpringBoot快速开始增删改查 小书MybatisPlus第2篇-条件构造器的应用及总结 小 ...
- Mybatis Generator实现分页功能
Mybatis Generator实现分页功能 分类: IBATIS2013-07-17 17:03 882人阅读 评论(1) 收藏 举报 mybatisibatisgeneratorpage分页 众 ...
- Springboot 系列(十二)使用 Mybatis 集成 pagehelper 分页插件和 mapper 插件
前言 在 Springboot 系列文章第十一篇里(使用 Mybatis(自动生成插件) 访问数据库),实验了 Springboot 结合 Mybatis 以及 Mybatis-generator 生 ...
- SpringBoot+Mybatis配置Pagehelper分页插件实现自动分页
SpringBoot+Mybatis配置Pagehelper分页插件实现自动分页 **SpringBoot+Mybatis使用Pagehelper分页插件自动分页,非常好用,不用在自己去计算和组装了. ...
- Mybatis+MySQL动态分页查询
https://blog.csdn.net/qq_34137397/article/details/63289621 mybatis有两种分页方法 1.内存分页,也就是假分页.本质是查出所有的数据然后 ...
- SpringBoot+Mybatis+PageHelper实现分页
SpringBoot+Mybatis+PageHelper实现分页 mybatis自己没有分页功能,我们可以通过PageHelper工具来实现分页,非常简单方便 第一步:添加依赖 <depend ...
随机推荐
- Eclipse Mars-Ant无法使用jre1.6的问题
https://www.jianshu.com/p/24b9517d7f43 Eclipse 升级到Mars 4.5.1版本后,老项目使用jdk1.6,通过ant编译jar时,会遇到如下问题: 使用j ...
- 派生类时使用private的目的 《私有派生》
第一:继承方式是public的情况下: 当成员是public的时候,派生类对象可以直接调用基类的这个方法和数据, 当数据是private的时候,派生类的对象不能直接调用之,可以通过调用基类的方法来访问 ...
- 01背包问题之2(dp)
01背包问题之2 有n个物品,重量和价值分别为wi和vi,从这些物品中挑选出重量不超过W的物品,求所有挑选方案中物品价值总和的最大值 限制条件: 1 <= n <= 100; 1 < ...
- 用老毛桃U盘安装:[3]Ghost版Win7系统
用老毛桃自动安装Ghost版Win7的步骤: 1,到网上先下载Ghost版Win7映像文件到硬盘,我放到的是U盘,盘符为Z,如果你愿意,可直接放到硬盘即可,放到硬盘安装速度会快一点. 2,把制作好的老 ...
- linux:ssh远程调用tomcat脚本时候出错
我们都知道,使用ssh在另一台机子执行一个ssh文件的语句是酱紫的 ssh root@1.9.7.56 "chmod 777 /opt/script/tomcatStop.sh ; sh / ...
- bluemix部署(二)构建kubernetes工作环境
本文接上篇.在bluemix中构建kubernetes容器. 1.创建集群 左上角的三横,选容器,然后创建集群. 注意区域,免费版,给个名字,创建集群吧. 继续正在部署,这个可能要15-30分钟,真不 ...
- MyBatis逆向工程:根据table生成Model、Mapper、Mapper.xml
逆向工程工具 下载地址:https://download.csdn.net/download/zhutouaizhuwxd/10779140 1.工程导入Eclipse 2.运行MainUI.jav ...
- 数据库编程测试机试 QQ
创建QQ数据库 #创建数据库 CREATE DATABASE QQ #创建表名 并且添加列 DROP TABLE IF EXISTS `dbo.BaseInfo`; CREATE TABLE `stu ...
- LSTM-自然语言建模
说到自然语言,我就会想到朴素贝叶斯,贝叶斯核心就是条件概率,而且大多数自然语言处理的思想也就是条件概率. 所以我用预测一个句子出现的概率为例,阐述一下自然语言处理的思想. 处理思想-概率 句子,就是单 ...
- Alpha冲刺1
前言 队名:拖鞋旅游队 组长博客:https://www.cnblogs.com/Sulumer/p/9948330.html 作业博客:https://edu.cnblogs.com/campus/ ...