• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Java > 在mybatis执行SQL语句之前进行拦击处理实例

在mybatis执行SQL语句之前进行拦击处理实例

作者:黄飞Gary 字体:[增加 减小] 来源:互联网 时间:2017-05-28

黄飞Gary 通过本文主要向大家介绍了拦击,乒乓球拦击,网页发行拦击,我的世界怎么拦击,mybatis打印sql语句等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

比较适用于在分页时候进行拦截。对分页的SQL语句通过封装处理,处理成不同的分页sql。

实用性比较强。

import java.sql.Connection; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.util.List; 
import java.util.Properties; 
 
import org.apache.ibatis.executor.parameter.ParameterHandler; 
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.mapping.ParameterMapping; 
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.yidao.utils.Page; 
import com.yidao.utils.ReflectHelper; 
 
/** 
 * 
 * 分页拦截器,用于拦截需要进行分页查询的操作,然后对其进行分页处理。 
 * 利用拦截器实现Mybatis分页的原理: 
 * 要利用JDBC对数据库进行操作就必须要有一个对应的Statement对象,Mybatis在执行Sql语句前就会产生一个包含Sql语句的Statement对象,而且对应的Sql语句 
 * 是在Statement之前产生的,所以我们就可以在它生成Statement之前对用来生成Statement的Sql语句下手。在Mybatis中Statement语句是通过RoutingStatementHandler对象的 
 * prepare方法生成的。所以利用拦截器实现Mybatis分页的一个思路就是拦截StatementHandler接口的prepare方法,然后在拦截器方法中把Sql语句改成对应的分页查询Sql语句,之后再调用 
 * StatementHandler对象的prepare方法,即调用invocation.proceed()。 
 * 对于分页而言,在拦截器里面我们还需要做的一个操作就是统计满足当前条件的记录一共有多少,这是通过获取到了原始的Sql语句后,把它改为对应的统计语句再利用Mybatis封装好的参数和设 
 * 置参数的功能把Sql语句中的参数进行替换,之后再执行查询记录数的Sql语句进行总记录数的统计。 
 * 
 */  
@Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class})}) 
public class PageInterceptor implements Interceptor { 
  private String dialect = ""; //数据库方言  
  private String pageSqlId = ""; //mapper.xml中需要拦截的ID(正则匹配)  
    
  public Object intercept(Invocation invocation) throws Throwable { 
    //对于StatementHandler其实只有两个实现类,一个是RoutingStatementHandler,另一个是抽象类BaseStatementHandler,  
    //BaseStatementHandler有三个子类,分别是SimpleStatementHandler,PreparedStatementHandler和CallableStatementHandler,  
    //SimpleStatementHandler是用于处理Statement的,PreparedStatementHandler是处理PreparedStatement的,而CallableStatementHandler是  
    //处理CallableStatement的。Mybatis在进行Sql语句处理的时候都是建立的RoutingStatementHandler,而在RoutingStatementHandler里面拥有一个  
    //StatementHandler类型的delegate属性,RoutingStatementHandler会依据Statement的不同建立对应的BaseStatementHandler,即SimpleStatementHandler、  
    //PreparedStatementHandler或CallableStatementHandler,在RoutingStatementHandler里面所有StatementHandler接口方法的实现都是调用的delegate对应的方法。  
    //我们在PageInterceptor类上已经用@Signature标记了该Interceptor只拦截StatementHandler接口的prepare方法,又因为Mybatis只有在建立RoutingStatementHandler的时候  
    //是通过Interceptor的plugin方法进行包裹的,所以我们这里拦截到的目标对象肯定是RoutingStatementHandler对象。 
    if(invocation.getTarget() instanceof RoutingStatementHandler){  
      RoutingStatementHandler statementHandler = (RoutingStatementHandler)invocation.getTarget();  
      StatementHandler delegate = (StatementHandler) ReflectHelper.getFieldValue(statementHandler, "delegate");  
      BoundSql boundSql = delegate.getBoundSql(); 
      Object obj = boundSql.getParameterObject(); 
      if (obj instanceof Page<?>) {  
        Page<?> page = (Page<?>) obj;  
        //通过反射获取delegate父类BaseStatementHandler的mappedStatement属性  
        MappedStatement mappedStatement = (MappedStatement)ReflectHelper.getFieldValue(delegate, "mappedStatement");  
        //拦截到的prepare方法参数是一个Connection对象  
        Connection connection = (Connection)invocation.getArgs()[0];  
        //获取当前要执行的Sql语句,也就是我们直接在Mapper映射语句中写的Sql语句  
        String sql = boundSql.getSql();  
        //给当前的page参数对象设置总记录数  
        this.setTotalRecord(page,  
            mappedStatement, connection);  
        //获取分页Sql语句  
        String pageSql = this.getPageSql(page, sql);  
        //利用反射设置当前BoundSql对应的sql属性为我们建立好的分页Sql语句  
        ReflectHelper.setFieldValue(boundSql, "sql", pageSql);  
      }  
    }  
    return invocation.proceed();  
  } 
   
  /** 
   * 给当前的参数对象page设置总记录数 
   * 
   * @param page Mapper映射语句对应的参数对象 
   * @param mappedStatement Mapper映射语句 
   * @param connection 当前的数据库连接 
   */  
  private void setTotalRecord(Page<?> page,  
      MappedStatement mappedStatement, Connection connection) {  
    //获取对应的BoundSql,这个BoundSql其实跟我们利用StatementHandler获取到的BoundSql是同一个对象。  
    //delegate里面的boundSql也是通过mappedStatement.getBoundSql(paramObj)方法获取到的。  
    BoundSql boundSql = mappedStatement.getBoundSql(page);  
    //获取到我们自己写在Mapper映射语句中对应的Sql语句  
    String sql = boundSql.getSql();  
    //通过查询Sql语句获取到对应的计算总记录数的sql语句  
    String countSql = this.getCountSql(sql);  
    //通过BoundSql获取对应的参数映射  
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();  
    //利用Configuration、查询记录数的Sql语句countSql、参数映射关系parameterMappings和参数对象page建立查询记录数对应的BoundSql对象。  
    BoundSql countBoundSql = new BoundSql(mappedStatement.getConfiguration(), countSql, parameterMappings, page);  
    //通过mappedStatement、参数对象page和BoundSql对象countBoundSql建立一个用于设定参数的ParameterHandler对象  
    ParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, page, countBoundSql);  
    //通过connection建立一个countSql对应的PreparedStatement对象。  
    PreparedStatement pstmt = null;  
    ResultSet rs = null;  
    try {  
      pstmt = connection.prepareStatement(countSql);  
      //通过parameterHandler给PreparedStatement对象设置参数  
      parameterHandler.setParameters(pstmt);  
      //之后就是执行获取总记录数的Sql语句和获取结果了。  
      rs = pstmt.executeQuery();  
      if (rs.next()) {  
       int totalRecord = rs.getInt(1);  
       //给当前的参数page对象设置总记录数  
       page.setTotalRecord(totalRecord);  
      }  
    } catch (SQLException e) {  
      e.printStackTrace();  
    } finally {  
      try {  
       if (rs != null)  
         rs.close();  
        if (pstmt != null)  
         pstmt.close();  
      } catch (SQLException e) {  
       e.printStackTrace();  
      }  
    }  
  }  
   
  /** 
   * 根据原Sql语句获取对应的查询总记录数的Sql语句 
   * @param sql 
   * @return 
   */  
  private String getCountSql(String sql) {  
    int index = sql.indexOf("from");  
    return "select count(*) " + sql.substring(index);  
  }  
   
  /** 
   * 根据page对象获取对应的分页查询Sql语句,这里只做了两种数据库类型,Mysql和Oracle 
   * 其它的数据库都 没有进行分页 
   * 
   * @param page 分页对象 
   * @param sql 原sql语句 
   * @return 
   */  
  private String getPageSql(Page<?> page, String sql) {  
    StringBuffer sqlBuffer = new StringBuffer(sql);  
    if ("mysql".equalsIgnoreCase(dialect)) {  
      return getMysqlPageSql(page, sqlBuffer);  
    } else if ("oracle".equalsIgnoreCase(dialect)) {  
      return getOraclePageSql(page, sqlBuffer);  
    }  
    return sqlBuffer.toString();  
  }  
   
  /** 
  * 获取My



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 在mybatis执行SQL语句之前进行拦击处理实例
  • 在mybatis执行SQL语句之前进行拦击处理实例

相关文章

  • 2017-05-28Maven+SSM框架实现简单的增删改查
  • 2017-05-28SWT JFace 拖曳效果
  • 2017-05-28java 中动态代理(JDK,cglib)实例代码
  • 2017-05-28SWT(JFace)体验之ViewForm的使用
  • 2017-05-28String类下compareTo()与compare()方法比较
  • 2017-05-28Java字符编码原理(动力节点Java学院整理)
  • 2017-05-28java中FileOutputStream中文乱码问题解决办法
  • 2017-05-28详解Spring Boot中使用AOP统一处理Web请求日志
  • 2017-05-28Spring Boot 简介(入门篇)
  • 2017-05-28浅谈将子类对象赋值给父类对象

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • SpringBoot集成Spring Data JPA及读写分离
    • 详解Java中的 枚举与泛型
    • spring注解识别一个接口的多个实现类方法
    • ByteArrayInputStream简介和使用_动力节点Java学院整理
    • springboot全局异常处理详解
    • Java微信公众平台开发(8) 多媒体消息回复
    • spring boot 使用@Async实现异步调用方法
    • java 类加载机制和反射详解及实例代码
    • mybatis教程之查询缓存(一级缓存二级缓存和整合ehcache)
    • Spring boot 整合CXF开发web service示例

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有