zoukankan      html  css  js  c++  java
  • Mybatis分页插件PageHelper简单使用

     

    一个好的讲解mybatis的博客地址http://www.jianshu.com/nb/5226994

    引言

    对于使用Mybatis时,最头痛的就是写分页,需要先写一个查询count的select语句,然后再写一个真正分页查询的语句,当查询条件多了之后,会发现真不想花双倍的时间写count和select,

    如下就是项目在没有使用分页插件的时候的语句

    复制代码
    <!-- 根据查询条件获取查询获得的数据量 -->
        <select id="size" parameterType="Map" resultType="Long">
            select count(*) from help_assist_student
            <where>
                <if test="stuId != null and stuId != ''">
                    AND stu_id like
                    CONCAT(CONCAT('%',
                    #{stuId,jdbcType=VARCHAR}),'%')
                </if>
                <if test="name != null and name != ''">
                    AND name like
                    CONCAT(CONCAT('%',
                    #{name,jdbcType=VARCHAR}),'%')
                </if>
                <if test="deptId != null">
                    AND dept_id in
                    <foreach item="item" index="index" collection="deptId" open="("
                        separator="," close=")">
                        #{item}
                    </foreach>
                </if>
                <if test="bankName != null">
                    AND bank_name in
                    <foreach item="item" index="index" collection="bankName"
                        open="(" separator="," close=")">
                        #{item}
                    </foreach>
                </if>
            </where>
        </select>
        <!-- 分页查询获取获取信息 -->
        <select id="selectByPageAndSelections" parameterType="cn.edu.uestc.smgt.common.QueryBase"
            resultMap="BaseResultMap">
            select * from help_assist_student
            <where>
                <if test="parameters.stuId != null and parameters.stuId != ''">
                    AND stu_id like
                    CONCAT(CONCAT('%',
                    #{parameters.stuId,jdbcType=VARCHAR}),'%')
                </if>
                <if test="parameters.name != null and parameters.name != ''">
                    AND name like
                    CONCAT(CONCAT('%',
                    #{parameters.name,jdbcType=VARCHAR}),'%')
                </if>
                <if test="parameters.deptId != null">
                    AND dept_id in
                    <foreach item="item" index="index" collection="parameters.deptId"
                        open="(" separator="," close=")">
                        #{item}
                    </foreach>
                </if>
                <if test="parameters.bankName != null">
                    AND bank_name in
                    <foreach item="item" index="index" collection="parameters.bankName"
                        open="(" separator="," close=")">
                        #{item}
                    </foreach>
                </if>
            </where>
            order by dept_id,stu_id
            limit #{firstRow},#{pageSize}
        </select>
    复制代码

    可以发现,重复的代码太多,虽然说复制粘贴简单的很,但是文件的长度在成倍的增加,以后翻阅代码的时候头都能大了。

    于是希望只写一个select语句,count由插件根据select语句自动完成。找啊找啊,发现PageHelperhttps://github.com/pagehelper/Mybatis-PageHelper 符合要求,于是就简单的写了一个测试项目

    1,配置分页插件:

    直接从官网上copy的如下:

    复制代码
    Config PageHelper
    
    1. Using in mybatis-config.xml
    
    <!-- 
        In the configuration file, 
        plugins location must meet the requirements as the following order:
        properties?, settings?, 
        typeAliases?, typeHandlers?, 
        objectFactory?,objectWrapperFactory?, 
        plugins?, 
        environments?, databaseIdProvider?, mappers?
    -->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!-- config params as the following -->
            <property name="param1" value="value1"/>
        </plugin>
    </plugins>
    2. Using in Spring application.xml
    
    config org.mybatis.spring.SqlSessionFactoryBean as following:
    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
      <!-- other configuration -->
      <property name="plugins">
        <array>
          <bean class="com.github.pagehelper.PageInterceptor">
            <property name="properties">
              <!-- config params as the following -->
              <value>
                param1=value1
              </value>
            </property>
          </bean>
        </array>
      </property>
    </bean>
    复制代码

    我使用第一中方法:

    复制代码
    <!-- 配置分页插件 -->
        <plugins>
            <plugin interceptor="com.github.pagehelper.PageInterceptor">
                <!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库-->
                <property name="helperDialect" value="mysql"/>
            </plugin>
        </plugins>

    <!--pagehelper 引入jar包也可以-->

    <dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.3</version>
    </dependency>
    复制代码

    其余的关于mybatis整合spring的内容就不用提了。

    2,编写mapper.xml文件

    测试工程就不复杂了,简单的查询一个表,没有条件

    <select id="selectByPageAndSelections" resultMap="BaseResultMap">
            SELECT *
            FROM doc
            ORDER BY doc_abstract
        </select>

    然后在Mapper.java中编写对应的接口

    public List<Doc> selectByPageAndSelections();

    3,分页

    复制代码
    @Service
    public class DocServiceImpl implements IDocService {
        @Autowired
        private DocMapper docMapper;
    
        @Override
        public PageInfo<Doc> selectDocByPage1(int currentPage, int pageSize) {
            PageHelper.startPage(currentPage, pageSize);
            List<Doc> docs = docMapper.selectByPageAndSelections();
            PageInfo<Doc> pageInfo = new PageInfo<>(docs);
            return pageInfo;
        }
    }
    复制代码

    参考文档说明,我使用了PageHelper.startPage(currentPage, pageSize);

    我认为这种方式不入侵mapper代码。

    其实一开始看到这段代码时候,我觉得应该是内存分页。其实插件对mybatis执行流程进行了增强,添加了limit以及count查询,属于物理分页

    再粘贴一下文档说明中的一段话

    复制代码
    4. 什么时候会导致不安全的分页?
    
    PageHelper 方法使用了静态的 ThreadLocal 参数,分页参数和线程是绑定的。
    
    只要你可以保证在 PageHelper 方法调用后紧跟 MyBatis 查询方法,这就是安全的。因为 PageHelper 在 finally 代码段中自动清除了 ThreadLocal 存储的对象。
    
    如果代码在进入 Executor 前发生异常,就会导致线程不可用,这属于人为的 Bug(例如接口方法和 XML 中的不匹配,导致找不到 MappedStatement 时), 这种情况由于线程不可用,也不会导致 ThreadLocal 参数被错误的使用。
    
    但是如果你写出下面这样的代码,就是不安全的用法:
    
    PageHelper.startPage(1, 10);
    List<Country> list;
    if(param1 != null){
        list = countryMapper.selectIf(param1);
    } else {
        list = new ArrayList<Country>();
    }
    这种情况下由于 param1 存在 null 的情况,就会导致 PageHelper 生产了一个分页参数,但是没有被消费,这个参数就会一直保留在这个线程上。当这个线程再次被使用时,就可能导致不该分页的方法去消费这个分页参数,这就产生了莫名其妙的分页。
    
    上面这个代码,应该写成下面这个样子:
    
    List<Country> list;
    if(param1 != null){
        PageHelper.startPage(1, 10);
        list = countryMapper.selectIf(param1);
    } else {
        list = new ArrayList<Country>();
    }
    这种写法就能保证安全。
    
    如果你对此不放心,你可以手动清理 ThreadLocal 存储的分页参数,可以像下面这样使用:
    
    List<Country> list;
    if(param1 != null){
        PageHelper.startPage(1, 10);
        try{
            list = countryMapper.selectAll();
        } finally {
            PageHelper.clearPage();
        }
    } else {
        list = new ArrayList<Country>();
    }
    这么写很不好看,而且没有必要。
    复制代码

    结语

     尽量不要重复造轮子。

    转载:http://www.cnblogs.com/ljdblog/p/6725094.html

  • 相关阅读:
    【流量劫持】SSLStrip 终极版 —— location 瞒天过海
    【流量劫持】沉默中的狂怒 —— Cookie 大喷发
    【流量劫持】SSLStrip 的未来 —— HTTPS 前端劫持
    Web 前端攻防(2014版)
    流量劫持 —— 浮层登录框的隐患
    流量劫持能有多大危害?
    流量劫持是如何产生的?
    XSS 前端防火墙 —— 整装待发
    XSS 前端防火墙 —— 天衣无缝的防护
    XSS 前端防火墙 —— 无懈可击的钩子
  • 原文地址:https://www.cnblogs.com/llfy/p/8466843.html
Copyright © 2011-2022 走看看