MyBatis之拦截器分页

鲁春利的工作笔记,好记性不如烂笔头



数据库的分页主要有物理分页和逻辑分页。
    物理分页:数据库本身提供的分页方式,如MySQL的limit、Oracle的rownum、SqlServer的top,好处是效率高,不好的地方就是不同数据库有不同的查询方式。
    逻辑分页:从数据库将所有记录查询出来,存储到内存中,然后数据再直接从内存中获取并筛选分页,好处是能够统一查询方式,不好的地方是效率低,因为每次都要把全部数据查询出来再处理。

常用orm框架采用的分页技术:
①:hibernate采用的是物理分页;
②:MyBatis使用RowBounds实现的分页是逻辑分页,也就是先把数据记录全部查询出来,然在再根据offset和limit截断记录。

MetaObject

org.apache.ibatis.reflection.MetaObject是Mybatis提供的一个的工具类,Mybatis在sql参数设置和结果集映射里经常使用到这个对象。

  • 属性:
  // 原始对象
  private Object originalObject;
  // 对原始对象的一个封装
  private ObjectWrapper objectWrapper;
  // org.apache.ibatis.reflection.factory.DefaultObjectFactory的父类
  private ObjectFactory objectFactory;
  // org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory的父类
  private ObjectWrapperFactory objectWrapperFactory;
  • 方法:
// 用于包装对象
MetaObject forObject(Object object,ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory)
// 用于获取属性的值(支持OGNL的方法)
Object getValue(String name)
// 用于设置属性的值(支持OGNL的方法)
void setValue(String name, Object value)

构造方法

  private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory) {
    this.originalObject = object;
    this.objectFactory = objectFactory;
    this.objectWrapperFactory = objectWrapperFactory;

    if (object instanceof ObjectWrapper) {
      this.objectWrapper = (ObjectWrapper) object;
    } else if (objectWrapperFactory.hasWrapperFor(object)) {
      this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
    } else if (object instanceof Map) {
      this.objectWrapper = new MapWrapper(this, (Map) object);
    } else if (object instanceof Collection) {
      this.objectWrapper = new CollectionWrapper(this, (Collection) object);
    } else {
      this.objectWrapper = new BeanWrapper(this, object);
    }
  }

forObject方法

  public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory) {
    if (object == null) {
      return SystemMetaObject.NULL_META_OBJECT;
    } else {
      return new MetaObject(object, objectFactory, objectWrapperFactory);
    }
  }

getValue

  public Object getValue(String name) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
      if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
        return null;
      } else {
          // 这里相当于递归调用,直到最后一层。例如user.cust.custId  
                // 第一次递归cust.custId  
                // 第二次递归custId,这个就是真正访问要返回的 
        return metaValue.getValue(prop.getChildren());
      }
    } else {
      return objectWrapper.get(prop);
    }
  }

setValue

  public void setValue(String name, Object value) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
      if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
        if (value == null && prop.getChildren() != null) {
          return; // don‘t instantiate child path if value is null
        } else {
          metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);
        }
      }
      metaValue.setValue(prop.getChildren(), value);
    } else {
      objectWrapper.set(prop, value);
    }
  }

拦截器签名

@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class})
    })
public class PreparePaginationInterceptor extends BaseInterceptor {

从签名里可以看出,要拦截的目标类型是StatementHandler(注意:type只能配置成接口类型),拦截的方法是名称为prepare参数为Connection类型的方法。

说明:关于为什么要把拦截器加到StatementHandler请参阅MyBatis之SqlSession介绍

时间: 2024-12-24 11:07:53

MyBatis之拦截器分页的相关文章

Mybatis最入门---分页查询(拦截器分页原理及实现)

[一步是咫尺,一步即天涯] 前文,我们演示了物理分页的Sql实现方式,这种方式使得我们每次在编写查询服务时,不断的重复造轮子.这样的代码实现方式就显得十分的笨拙了.本文是Mybatis分页查询的最后一片内容,我们将介绍基于拦截器的,精巧的实现方式.在阅读这篇文章之前,强烈建议各位看官能够先阅读上文.这样就能对下文我们提及的各种对象及他们之间的关系有一个清晰的关系.好了,废话不多讲,开始我们的正文部分吧. 准备工作: a.操作系统 :win7 x64 b.基本软件:MySQL,Mybatis,SQ

Mybatis Interceptor 拦截器原理 源码分析

Mybatis采用责任链模式,通过动态代理组织多个拦截器(插件),通过这些拦截器可以改变Mybatis的默认行为(诸如SQL重写之类的),由于插件会深入到Mybatis的核心,因此在编写自己的插件前最好了解下它的原理,以便写出安全高效的插件. 代理链的生成 Mybatis支持对Executor.StatementHandler.PameterHandler和ResultSetHandler进行拦截,也就是说会对这4种对象进行代理. 通过查看Configuration类的源代码我们可以看到,每次都

spring mvc 配置 mybatis sql拦截器

直接上代码: mybatis配置中 添加  <property name="plugins"> 如下: <bean id="sqlSessionFactory" class="com.hotent.core.mybatis.SqlSessionFactoryFactoryBean"> <property name="configLocation" value="classpath:/co

Mybatis之拦截器--获取执行SQL实现多客户端数据同步

最近的一个项目是将J2EE环境打包安装在客户端(使用 nwjs + NSIS 制作安装包)运行, 所有的业务操作在客户端完成, 数据存储在客户端数据库中. 服务器端数据库汇总各客户端的数据进行分析. 其中客户端ORM使用Mybatis. 通过Mybatis拦截器获取所有在执行的SQL语句, 定期同步至服务器. 本文通过在客户端拦截SQL的操作介绍Mybatis拦截器的使用方法. 1. 项目需求 客户分店较多且比较分散, 部分店内网络不稳定, 客户要求每个分店在无网络的情况下也能正常使用系统, 同

mybatis - 基于拦截器修改执行中的SQL语句

拦截器介绍 mybatis提供了@Intercepts注解允许开发者对mybatis的执行器Executor进行拦截. Executor接口方法主要有update.query.commit.rollback等等. 主要思路为: 进入拦截器方法中 获取拦截器方法参数 获取解析参数及SQL 自定义生成自己的SQL语句 将自定义SQL设置进参数中 由mybatis处理后续问题 拦截器代码 import org.apache.ibatis.cache.CacheKey; import org.apach

mybatis拦截器分页

package com.test.interceptor; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import java.util.Map; import java.util.Properties; import org.apache.ibatis.executor.Executor; import org.apache

bean 和 Map 的相互转换(Mybatis 拦截器分页--将Object的参数对象封装到Pager 的params 中)

1 apache 的beanUtils 工具类,只能将Bean 转换成 Map<String,String>类型,不能转换成 Map<String,Object> 2 借助工具类DozerBeanMapper 需要引入的jar 有dozer.jar  此外还包含:slf4j.jar,commons-lang.jar,commons-beanutil.jar, commons-loggin.jar 3 写自定义工具类 import org.dozer.DozerBeanMapper;

mybatis使用拦截器显示sql,使用druid配置连接信息

a:focus { outline: thin dotted #333; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } a:hover { outline: 0; } a:active { outline: 0; } a:hover { color: #005580 !important; text-decoration: underline !important; } blockquote small:b

由浅入深分析mybatis通过动态代理实现拦截器(插件)的原理

最近在用mybatis做项目,需要用到mybatis的拦截器功能,就顺便把mybatis的拦截器源码大致的看了一遍,为了温故而知新,在此就按照自己的理解由浅入深的理解一下它的设计. 和大家分享一下,不足和谬误之处欢迎交流.直接入正题. 首先,先不管mybatis的源码是怎么设计的,先假设一下自己要做一个拦截器应该怎么做.拦截器的实现都是基于代理的设计模式设计的,简单的说就是要创造一个目标类的代理类,在代理类中执行目标类的方法并拦截执行拦截器代码. 那么我们就用JDK的动态代理设计一个简单的拦截器