ibatis基于拦截器的分页实现

OpenModelica入门指南:从下载安装到第一个仿真模型(附常见问题解答) 本文提供OpenModelica开源项目的完整入门指南,涵盖从下载安装、界面熟悉到构建首个仿真模型的全过程。通过创建经典的阻尼震荡系统实例,详细讲解组件拖放、参数设置、仿真运行及结果分析,并附有常见问题解决方案,帮助工程师和研究人员快速上手这一强大的多领域物理系统建模与仿真工具。 阅读详情

ibatis基于拦截器的分页实现

1、在spring配置文件(applicationContext.xml)中添加拦截器配置:

<!-- 分页插件,根据方言自动添加分页信息,默认要求 -->
<bean id="pagePlugin" class="com.ifdoo.core.mybatis.plugin.PagePlugin">
    <property name="properties">
        <props>
            <prop key="dialect">com.ifdoo.core.mybatis.dialet.MySQLDialect</prop>
            <prop key="pageSqlId">.*query.*</prop>
        </props>
    </property>
</bean>

2、PagePlugin.java



import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import javax.xml.bind.PropertyException;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.statement.BaseStatementHandler;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
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.scripting.defaults.DefaultParameterHandler;

import com.ifdoo.core.exception.SystemException;
import com.ifdoo.core.mybatis.dialet.Dialect;
import com.ifdoo.core.utils.page.PageView;

/**
 * Mybatis的分页查询插件,通过拦截StatementHandler的prepare方法来实现。
 * 只有在参数列表中包括Page类型的参数时才进行分页查询。 在多参数的情况下,只对第一个Page类型的参数生效。
 * 另外,在参数列表中,Page类型的参数无需用@Param来标注
 * 
 * @version 1.0
 */
@SuppressWarnings("unchecked")
@Intercepts( { @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class PagePlugin implements Interceptor {

    private static Dialect  dialectObject   = null; // 数据库方言
    private static String   pageSqlId       = "";   // mybaits的数据库xml映射文件中需要拦截的ID(正则匹配)

    @SuppressWarnings("rawtypes")
    public Object intercept(Invocation ivk) throws Throwable {
        if (ivk.getTarget() instanceof RoutingStatementHandler) {
            RoutingStatementHandler statementHandler = (RoutingStatementHandler) ivk.getTarget();
            BaseStatementHandler delegate = (BaseStatementHandler) ReflectHelper.getValueByFieldName(statementHandler, "delegate");
            MappedStatement mappedStatement = (MappedStatement) ReflectHelper.getValueByFieldName(delegate, "mappedStatement");
            /**
             * 方法1:通过ID来区分是否需要分页..*query.* 方法2:传入的参数是否有page参数,如果有,则分页,
             */
            // if (mappedStatement.getId().matches(pageSqlId)) { // 拦截需要分页的SQL
            BoundSql boundSql = delegate.getBoundSql();
            Object parameterObject = boundSql.getParameterObject();// 分页SQL<select>中parameterType属性对应的实体参数,即Mapper接口中执行分页方法的参数,该参数不得为空
            if (parameterObject == null) {
                // throw new
                // NullPointerException("boundSql.getParameterObject() is null!");
                return ivk.proceed();
            } else {

                PageView pageView = null;
                if (parameterObject instanceof PageView) { // 参数就是Pages实体
                    pageView = (PageView) parameterObject;
                } else if (parameterObject instanceof Map) {
                    for (Entry entry : (Set<Entry>) ((Map) parameterObject).entrySet()) {
                        if (entry.getValue() instanceof PageView) {
                            pageView = (PageView) entry.getValue();
                            break;
                        }
                    }
                } else { // 参数为某个实体,该实体拥有Pages属性
                    pageView = ReflectHelper.getValueByFieldType(parameterObject, PageView.class);
                    if (pageView == null) {
                        return ivk.proceed();
                    }
                }

                if (pageView == null) {
                    return ivk.proceed();
                }

                String sql = boundSql.getSql();
                PreparedStatement countStmt = null;
                ResultSet rs = null;
                try {
                    Connection connection = (Connection) ivk.getArgs()[0];
                     String countSql = "select count(1) from (" + sql
                     + ") tmp_count"; // 记录统计
//                   String countSql = "select count(1) from (" + sql +
//                   ") tmp_count"; // 记录统计
//                   ") tmp_count"; // 记录统计

//                  String countSql = "";// "select count(1) from (" + sql +
//                  // 拼装count SQL
//                  int from_index = 0;
//                  if ((from_index = StringUtils.indexOfIgnoreCase(sql, "from")) != -1) {
//                      countSql = "select count(1) " + sql.substring(from_index, sql.length());
//                  }
//                  int order_index = 0;
//                  if ((order_index = StringUtils.lastIndexOfIgnoreCase(countSql, "order")) != -1) {
//                      countSql = countSql.substring(0, order_index);
//                  }

                    countStmt = connection.prepareStatement(countSql);
                    ReflectHelper.setValueByFieldName(boundSql, "sql", countSql);
                    DefaultParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);
                    parameterHandler.setParameters(countStmt);
                    rs = countStmt.executeQuery();
                    int count = 0;
                    if (rs.next()) {
                        count = ((Number) rs.getObject(1)).intValue();
                    }

                    if (null != pageView) {
                        pageView.setRowCount(count);
                    }
                } finally {
                    try {
                        rs.close();
                    } catch (Exception e) {
                    }
                    try {
                        countStmt.close();
                    } catch (Exception e) {
                    }
                }
                String pageSql = generatePagesSql(sql, pageView);
                ReflectHelper.setValueByFieldName(boundSql, "sql", pageSql); // 将分页sql语句反射回BoundSql.
            }
            // }
        }
        return ivk.proceed();
    }

    /**
     * 根据数据库方言,生成特定的分页sql
     * 
     * @param sql
     * @param page
     * @return
     */
    @SuppressWarnings("rawtypes")
    private String generatePagesSql(String sql, PageView page) {
        if (page != null && dialectObject != null) {
            // pageNow默认是从1,而已数据库是从0开始计算的.所以(page.getPageNow()-1)
            int pageNow = page.getPageNow();
            return dialectObject.getLimitString(sql, (pageNow <= 0 ? 0 : pageNow - 1) * page.getPageSize(), page.getPageSize());
        }
        return sql;
    }

    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    public void setProperties(Properties p) {
        String dialect = ""; // 数据库方言
        dialect = p.getProperty("dialect");
        if (StringUtils.isBlank(dialect)) {
            try {
                throw new PropertyException("dialect property is not found!");
            } catch (PropertyException e) {
                throw new SystemException(e);
            }
        } else {
            try {
                dialectObject = (Dialect) Class.forName(dialect).getDeclaredConstructor().newInstance();
            } catch (Exception e) {
                throw new RuntimeException(dialect + ", init fail!\n" + e);
            }
        }
        pageSqlId = p.getProperty("pageSqlId");// 根据id来区分是否需要分页
        if (StringUtils.isBlank(pageSqlId)) {
            try {
                throw new PropertyException("pageSqlId property is not found!");
            } catch (PropertyException e) {
                throw new SystemException(e);
            }
        }
    }
}

3、Dialect.java


/**
 * 类似hibernate的Dialect,但只精简出分页部分
 */
public class Dialect {

    public boolean supportsLimit(){
        return false;
    }

    public boolean supportsLimitOffset() {
        return supportsLimit();
    }

    /**
     * 将sql变成分页sql语句,直接使用offset,limit的值作为占位符.</br>
     * 源代码为: getLimitString(sql,offset,String.valueOf(offset),limit,String.valueOf(limit))
     */
    public String getLimitString(String sql, int offset, int limit) {
        return getLimitString(sql,offset,Integer.toString(offset),limit,Integer.toString(limit));
    }

    /**
     * 将sql变成分页sql语句,提供将offset及limit使用占位符(placeholder)替换.
     * <pre>
     * 如mysql
     * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回
     * select * from user limit :offset,:limit
     * </pre>
     * @return 包含占位符的分页sql
     */
    public String getLimitString(String sql, int offset,String offsetPlaceholder, int limit,String limitPlaceholder) {
        throw new UnsupportedOperationException("paged queries not supported");
    }

}

4、MySQLDialect.java

public class MySQLDialect extends Dialect{

    public boolean supportsLimitOffset(){
        return true;
    }

    public boolean supportsLimit() {   
        return true;   
    }  

    public String getLimitString(String sql, int offset,String offsetPlaceholder, int limit, String limitPlaceholder) {
        if (offset > 0) {   
            return sql + " limit "+offsetPlaceholder+","+limitPlaceholder; 
        } else {   
            return sql + " limit "+limitPlaceholder;
        }  
    }   
}

针对于其他数据库的分页方言处理在后面博客中添加,谢谢!

SUMO仿真教程(5) —— 使用“XML“语言自定义构建路网 文章目录一.简要介绍1.node file2.edge file3.lane definitions(1)路段细分(2)邻近的对向车道(3)删除边或车道4.type file(1)简要概述(2)edge定义中引用type文件的示例(3)指定车辆种类的速度限制5.connections file(1)简要概述:(2)connection的属性参数(3)删除连接(4)设置连接的优先级(5)同一边的多个连接二.演示示例:1.自定义编写node file2.自定义编写edge file3.自定义编写type fil 阅读详情

相关推荐

Deepseek 10分钟化身理性荐股神器:触碰程序员不敢想的天花板

在这个消息疯狂、波动频繁的市场,“理性”两字显得弥足珍贵。通过Deepseek+AkShare+Aktools+Dify四位一体的方案,能帮我们降低信息搜集成本,并在短期投资领域搭建出一套“可解释、低门槛、易定制”的量化荐股流程。不要再盲目听小道消息或依赖情绪驱动,不妨给自己一个机会,让数据说话。而要注意的是,“理性荐股”并非万能,它只是工具,最终的收益还得依赖投资者自身对风险和机遇的权衡。祝大家都能在这股市里收获理性的底气,寻得更精准的入场时机。

qqxdh的博客 3755

Mybatis 拦截器

拦截org.apache.ibatis.resultset.ResultSetHandler接口的方法,用于处理数据库返回的结果集,将结果集中的数据映射到Java对象上。拦截org.apache.ibatis.executor.Executor接口的方法,主要用于处理SQL语句的执行过程,包括查询、更新、插入和删除等操作。拦截org.apache.ibatis.mapping.ParameterHandler接口的方法,负责设置SQL预编译语句中的参数值。如动态SQL的解析与拼接、添加额外的查询条件等。

张紫娃的博客 757

ADS谐波平衡仿真自动优化报错?三步搞定HB控件设置(附常见错误排查)

本文针对ADS谐波平衡仿真在自动优化中常见的报错问题,提供了三步核心排查法。首先检查并禁用HB控件中可能导致冲突的小信号仿真模式,其次合理化仿真频率与扫描参数设置,最后审视优化变量与目标的定义。通过精准配置HB控件以适配自动优化流程,能有效解决大多数仿真失败问题,确保非线性电路设计顺利进行。

c2d3e4f的博客 792

分页拦截器 iBatis MyBatis Page

分页拦截器 @Override public Page findBsProcList4Page(BsProcListQuery param) { if(param == null){ return new Page(param.getCurrentPage(), param.getPageSize(), 0L, null); } // 过滤已经删除的数据 param.setStatus((byte) 0);

ambi_garlic的博客 240

ESP32连接OneNet云平台实现多设备联动控制完整示例

通过esp32连接onenet云平台,实现远程设备间的智能联动控制,利用MQTT协议完成数据通信,esp32连接onenet云平台后可高效稳定地上传与下发指令,提升物联网系统响应速度与自动化水平。

weixin_42360733的博客 548

从Oracle迁移数据到Hadoop

目标:把Oracle 下的数据文件迁移到 Hadoop , 数据表都是上亿条,每个数据表的空间都超过100G。 关键是建立数据文件是UTF8格式,这样数据中的汉字在Hadoop 里显示才正常。 平台:CentOS 6.10 工具:Python 2.7 cx_Oracle 库 Oracle10.2.0.4.0 Hadoop 2.7.2-transwarp-5.2.1 1. 查看表...

预则立 4238

拦截所有ibatissql执行_Mybatis源码学习(四)拦截器与插件原理

一、mybatis执行过程和架构· 加载回顾前几文加载mybatis时,会通过sqlSessionFactoryBuilder的build方法对xml文件进行解析,解析成document树后,再依次对树中的XNode结点进行解析,如xml配置中的plugins、environments、mappers、typeHandlers等基础配置信息,初始化后赋值给configurati...

weixin_34885746的博客 820

UWB定位进阶:如何利用DW1000的CIR数据做NLOS信号识别?

本文深入探讨了如何利用DW1000芯片的信道脉冲响应(CIR)数据进行非视距(NLOS)信号识别,以提升UWB定位精度。通过分析CIR数据的核心价值、预处理方法、特征提取技术以及机器学习模型构建,为研究人员和工程师提供了实用的解决方案,帮助克服室内定位中的NLOS挑战。

weixin_28729205的博客 474

ibatis中SQL查询耗时监控拦截器

【代码】ibatis中SQL查询耗时监控拦截器。

u012917290的博客 432

从0到1用OpenClaw打造酒店收益管理系统:数据整合→AI策略迭代全链路落地实战

本文基于三亚某连锁海景酒店真实项目落地经验编写,系统上线3个月,酒店平均入住率从62%提升至80%,RevPAR(平均可售房收入)提升26%,淡季空置率降低46%,完全覆盖中小酒店全场景收益管理需求。本文配套OpenClaw全量Skill代码、工作流配置文件,可直接复用落地。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 495

2026 年 3 月青少年软编等考 C/C++ 三级测试题解析

摘要 本文包含三部分内容: 单选题(10题):考察C++基础语法和数据结构知识,涉及vector、栈、队列的操作和特性。 判断题(10题):测试对动态数组、栈、队列、字符串操作的理解,包括内存管理、访问方式和函数返回值等。 编程题(1题):模拟火车站售票窗口排队场景,要求根据输入输出各窗口的排队情况,重点考查队列的实际应用和边界条件处理。 答案解析详细,涵盖常见编程考点,适合检验基础知识的掌握程度。

发布少儿编程考级的真题和优秀竞赛题解析,以及一些讲义。 253

MyBatis 四种类型拦截器

在 MyBatis 中,拦截器(Interceptor)是一种强大的机制,用于拦截 SQL 语句的执行过程,可以在执行 SQL 前后进行一些自定义的操作,比如日志记录、权限验证、性能监控等。在 MyBatis 中,拦截器主要通过实现接口来实现。

a_beiyo的博客 680

Autosar EcuM配置-初始化及下电执行函数-基于ETAS软件

Autosar EcuM学习笔记-上电初始化执行函数及下电前执行函数,本文介绍在EcuM中的配置及使用。

赞的博客 851

IBatis框架的一些问题的扩展(一)

          今年开发的项目XX项目中采用IBatis2.0+RCP +EJB3.0作为项目的架构,其中IBatis作为持久化框架,不采用Hibernate的原因很多,其中系统的高并发,高性能,大数据库量,消息通信类的系统,实时处理系统,偏向数据分析的系统等要求,同时由于hibernate技术的成败取决于开发人员的水平,由于人员水平参差不齐,无法保证对开源项目的实现掌控等原因,可能hib...

topMan'blog 330

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

mysql dialect配置_iBatis3基于方言(Dialect)的分页

(注:以下代码是基于ibatis3 beta4的扩展,ibatis3正式版如果实现改变,将会继续跟进修改)iBatis3默认使用的分页是基于游标的分页,而这种分页在不同的数据库上性能差异不一致,最好的办法当然是使用类似hibernate的基于方言(Dialect)的物理分页功能。iBatis3现在提供插件功能,通过插件我们可以编写自己的拦截器来拦截iBatis3的主要执行方法来完成相关功能的扩展。...

weixin_39926042的博客 474

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

iBatis3基于方言(Dialect)的分页

iBatis3基于方言(Dialect)的分页 博客分类: Rapid-framework SQLMySQLJDBCiBATISSVN (注:以下代码是基于ibatis3 beta4的扩展,ibatis3正式版如果实现改变,将会继续跟进修改) iBatis3默认使用的分页是基于游标的分页,而这种分页在不同的数据库上性能差异不一致,最好的办法当然是使用类似hibern

gaoshanliushui2009的专栏 3882

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

mybatis mysql 方言_iBatis3基于方言(Dialect)的分页

(注:以下代码是基于ibatis3 beta4的扩展,ibatis3正式版如果实现改变,将会继续跟进修改)iBatis3默认使用的分页是基于游标的分页,而这种分页在不同的数据库上性能差异不一致,最好的办法当然是使用类似hibernate的基于方言(Dialect)的物理分页功能。iBatis3现在提供插件功能,通过插件我们可以编写自己的拦截器来拦截iBatis3的主要执行方法来完成相关功能的扩展。...

weixin_33514163的博客 1704

iBatis3 Dialect 分页

参考以前论坛中关于ibatis2 Dialect 分页思路,实现iBatis3 Dialect 分页,由于ibatis3结构重新设计,提供了interceptor功能,有几个切入点,使得我们可以修改运行sql语句和处理返回结果 1:修改sql语句 [code="java"] import java.sql.Connection; import java.util.Propertie...

melin1204的博客 174

java里dialect_iBatis3基于方言(Dialect)的分页

(注:以下代码是基于ibatis3 beta4的扩展,ibatis3正式版如果实现改变,将会继续跟进修改)iBatis3默认使用的分页是基于游标的分页,而这种分页在不同的数据库上性能差异不一致,最好的办法当然是使用类似hibernate的基于方言(Dialect)的物理分页功能。iBatis3现在提供插件功能,通过插件我们可以编写自己的拦截器来拦截iBatis3的主要执行方法来完成相关功能的扩展。...

weixin_39814925的博客 484

pageHelper的分页

PagerHelper的分页,看了十几分钟。核心是利用Ibatis的拦截器,进行拦截。 拦截后针对不行的sql服务,比如mysql,sqlserver写方言,添加分页机制 /* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of th

qq_30177469的博客 255

spring同时集成mybatis和ibatis

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33747129的博客 183

MyBaits 之八:MyBatis 拦截器及自定义分页插件

MyBatis允许开发者在映射语句执行过程中的某一些指定的节点进行拦截调用,通过织入拦截器,在不同节点修改一些执行过程中的关键属性,从而影响SQL的生成、执行和返回结果; 比如:之前的分页插件的实现,就是使用拦截器(插件)来实现的 基本步骤: 实现 Interceptor 并 配置注解 @Intercepts 配置文件中配置插件

zp8126的专栏 1811

Mybatis拦截器介绍及分页插件

Mybatis拦截器介绍及分页插件 1.1    目录 1.1 目录 1.2 前言 1.3 Interceptor接口 1.4 注册拦截器 1.5 Mybatis可拦截的方法 1.6 利用拦截器进行分页 1.2     前言        拦截器的一个作用就是我们可以拦截某些方法的调用,我们可以选择在这些被拦截的方法执行前后加上某些逻辑,也可以在执行这些被拦截的方法时执行自己的逻

Elim的博客 1万+

ibatis mysql分页查询语句_Mybatis 分页详解

前言在学习mybatis等持久层框架的时候,会经常对数据进行增删改查操作,使用最多的是对数据库进行查询操作,如果查询大量数据的时候,我们往往使用分页进行查询,也就是每次处理小部分数据,这样对数据库压力就在可控范围内。分页的几种方式1. 内存分页内存分页的原理比较sb,就是一次性查询数据库中所有满足条件的记录,将这些数据临时保存在集合中,再通过List的subList方法,获取到满足条件的记录,由于...

weixin_29015127的博客 603
下一篇: SpringMvc整合ehcaech
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值