MyBatis源码学习(二)

栏目: Java · 发布时间: 6年前

内容简介:看完趣味数学书后,开始技术填坑之路通常在业务中,需要进行数据分页查询,这样一来,每条SQL语句都加上limit限制,会多了很多重复的代码,而且每次需要自己在代码中进行偏移量的计算,略微有些麻烦。还好有大神在
MyBatis源码学习(二)

看完趣味数学书后,开始技术填坑之路

通常在业务中,需要进行数据分页查询,这样一来,每条 SQL 语句都加上limit限制,会多了很多重复的代码,而且每次需要自己在代码中进行偏移量的计算,略微有些麻烦。

还好有大神在 Github 里贡献了分页插件,而且使用起来很方便,了解了一下使用原理,发现是使用了MyBatis里面的拦截器Interceptor,学习记录一下。

简单:chestnut:

项目中进行引用

一般JavaWeb项目使用到的是maven和gradle进行项目管理

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>最新版本</version>
</dependency>

···

// https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper
compile group: 'com.github.pagehelper', name: 'pagehelper', version: '5.1.4'

复制代码

在mybatis-config或者spring中进行配置

mybatis:
<plugins>
    <!-- com.github.pagehelper为PageHelper类所在包名 -->
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
        <!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->
        <property name="param1" value="value1"/>
	</plugin>
</plugins>

spring:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!-- 自动扫描mapping.xml文件 -->
        <property name="mapperLocations" value="classpath:mapping/*.xml">
        </property>
        <!-- 配置分页插件 -->
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <value>
                            reasonable=true
                        </value>
                    </property>
                </bean>
            </array>
        </property>
    </bean>
复制代码

我是用的是第二种配置方式(Spring),更加细详细配置说明可以在Github文档中进行查看。

mapper查询语句

为了简单,使用了单表查询

<select id="selectByUserId" resultMap="BaseResultMap">
    SELECT
    <include refid="Base_Column_List" />
    FROM course_user
    WHERE user_id = #{userId, jdbcType=INTEGER}
</select>
复制代码

代码使用

查询时,在代码中使用的是官网推荐的第二种实现方式,

// 使用这个方法,接下来的第一个select方法会进行分页
PageHelper.startPage(1, 5);
List<CourseUser> list = mapper.selectByUserId(userId);
// 查询结果list类型是Page<E>,要取出分页信息,可以强转,也可以使用PageInfo
// 用PageInfo对结果进行包装
PageInfo page = new PageInfo(list);
// 获取总数量
int count = page.getTotal();
复制代码

分页插件,源码实现原理

该插件支持很多数据库,Oracle、 MySQL 、mongdb等都支持,一般常用的话是MySQL,测试用的项目也是使用MySQL作为持久层,该分页插件可以通过autoDialect自动方言适配了MySQL。

插件通过MyBatis的 拦截器Interceptor进行SQL重写 ,可以从源码中看出

统计数量

拦截器入口:com.github.pagehelper.PageInterceptor#intercept

获取统计数量的方法:com.github.pagehelper.parser.CountSqlParser#getSmartCountSql(java.lang.String, java.lang.String)

/**
 * 获取智能的countSql
 *
 * @param sql
 * @param name 列名,默认 0
 * @return
 */
public String getSmartCountSql(String sql, String name) {
    //解析SQL
    Statement stmt = null;
    //特殊sql不需要去掉order by时,使用注释前缀
    if(sql.indexOf(KEEP_ORDERBY) >= 0){
        return getSimpleCountSql(sql);
    }
    try {
        stmt = CCJSqlParserUtil.parse(sql);
    } catch (Throwable e) {
        //无法解析的用一般方法返回count语句
        return getSimpleCountSql(sql);
    }
    Select select = (Select) stmt;
    SelectBody selectBody = select.getSelectBody();
    try {
        //处理body-去order by
        processSelectBody(selectBody);
    } catch (Exception e) {
        //当 sql 包含 group by 时,不去除 order by
        return getSimpleCountSql(sql);
    }
    //处理with-去order by
    processWithItemsList(select.getWithItemsList());
    //处理为count查询
    sqlToCount(select, name);
    String result = select.toString();
    return result;
}
复制代码

通过该方法,去掉参数args,然后改成count(*),修改成统计数量的SQL。

进行分页查询

具体调用方法:com.github.pagehelper.dialect.helper.MySqlDialect#getPageSql

@Override
public String getPageSql(String sql, Page page, CacheKey pageKey) {
    StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14);
    sqlBuilder.append(sql);
    // 判断是不是第一页,如果是第一页,不需要设置偏移量
    if (page.getStartRow() == 0) {
        sqlBuilder.append(" LIMIT ? ");
    } else {
        sqlBuilder.append(" LIMIT ?, ? ");
    }
    pageKey.update(page.getPageSize());
    return sqlBuilder.toString();
}
复制代码

从这里看出,该插件不是通过内存进行分页,而是通过修改SQL进行物理分页。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Learning JavaScript

Learning JavaScript

Shelley Powers / Oreilly & Associates Inc / 2006-10-17 / $29.99

As web browsers have become more capable and standards compliant, JavaScript has grown in prominence. JavaScript lets designers add sparkle and life to web pages, while more complex JavaScript has led......一起来看看 《Learning JavaScript》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

在线进制转换器
在线进制转换器

各进制数互转换器

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试