PageHelper好用吗?mybatis+layuiAdmin 纯手撸整套分页查询代码。

开始

如果mybatis项目中要使用分页插件,我相信大部分人都使用PageHelper。

优点:

1.通过执行sql语句前拦截的方式,为sql追加limit语句,并自动执行计算count的SQL语句。使分页代码与mapper.xml分离,不需要在mapper.xml中添加分页语句。

2.支持各种数据库和框架,支持换库支持多库同操云云。

但是也存在几个缺点:

1.需要增加很多配置及额外代码。

2.支持多种数据库和框架但普通中小型项目并不受益(开发中没事换什么数据库结构和框架?)。

3.数据量大时,性能不如原生。

4.未能很好解决前端分页查询时,多条件筛选的问题(PageHelper是传入一个带条件map,条件仍需自己在select标签中实现)。

5.一些实际开发中很复杂sql的count语句,仍然需要自己写(比如复杂业务中的订单货单查询)。

总而言之,各类分页插件,肯定有很多的优点,但它们的优点却不一定能戳中项目的痛点。

所以熟练地编写底层分页逻辑是很有必要的,明白底层原理之后,我们将会知道项目该不该使用分页插件,该使用哪个分页插件。

甚至自己手撸个很棒的分页组件也不在话下。

一、开发环境

后台:spring-boot2,mybatis,mysql
前端:jquery,layui
(只有分页涉及的框架,其他框架未列出)

笔者上个项目是商场支付管理+产品营销项目,供应链逻辑并没多少,反而前端特效特别多,于是舍弃vue-elementui,果断使用笔者娴熟的jquery。UI框架则尝试了口碑愈佳的Layui。

不得不说 Layui 是非常好用的UI框架(吹一波,无广告),稍微改动便可在手机端完美重现,且系统兼容性目前没有太大问题。

二、前言

本来是打算写部分关键代码片段的,但我以前逛文章的时候,总发现评论有一些刚刚入门的开发者,看不明白。

毕竟本猿是初出茅庐的小编,在记录心得的同时,也要为入门的开发者们着想,所以以下会贴出所有关键的代码,并贴出文件名,如果有任何问题可以留言解决,有问题也请指出,共同学习。

三、实现代码

3.1 先看看要实现的最终前端页面

在这里插入图片描述

包含以下功能:

  • 分页展示数据
  • 点击价格标题栏的上下箭头,进行所有数据按照价格排序(自主排序)
  • 分页查询时进行多条件筛选(示例不多,但经常会有很多筛选条件)

关于多条件筛选,我之前对sql拼接方式实现的思路,有过详细的分析(传送门)。

3.2 数据层mybatis三件套代码

entity:MGood.java

package com.core.jjtm.entity;
import com.core.jjtm.entity.extendClass.EntityPager;
import com.core.jjtm.utils.TimeFormater;
import org.hibernate.annotations.CreationTimestamp;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.*;

@Entity
@Table(name = "m_good")
public class MGood extends EntityPager {

	//这些注解都是JPA注解,我其实用的JPA + mybatis,用JPA托管简单的SQL查询,可以忽视这些注解
    @Id
    private String id;
    private String type;
    private String name;
    private String specs;
    private String imgs;
    private String storeid;
    private String fromgoodid;
    private BigDecimal unitprice;
    private BigDecimal price;
    private String note;

    @Temporal(TemporalType.TIMESTAMP)
    @CreationTimestamp   //此注解,JPA会在插入数据时,自动补全创建时间
    private Date crttime;

    /****************************链表查询*******************************/
    @Transient
    private String fromstorename,fromstoreid;
    @Transient
    private BigDecimal count;
    //省略 getter,setter  实际开发中可以使用注解方式免去

	//创建时间的getter小技巧,提供两个getter,
	//getCrttime(),供前端还原页面使用
	//getCrttimeObj(),供后台使用
	public String getCrttime() {
        return TimeFormater.toStr(crttime,"yyyy-MM-dd HH:mm:ss");
    }
    public Date getCrttimeObj() {
        return crttime;
    }

entity继承的类:EntityPager.java

c是筛选条件,m,n是分页参数,o是排序条件字符串

package com.core.jjtm.entity.extendClass;
import javax.persistence.Transient;

public class EntityPager {
	//这些注解都是JPA注解,我其实用的JPA + mybatis,用JPA托管简单的SQL查询,可以忽视这些注解
    @Transient
    private String c,m,n,o;
    //省略 getter,setter  实际开发中可以使用注解方式免去
    //c的getter,进行sql片段拼接
    public String getC() {
        return parseCondtionSql(c);
    }
    
	/**
     * 将condition对象列表解析成sql语句
     **/
    private String parseCondtionSql(String condition) {
        if (condition == null || isEmptyStr(condition)) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        List<Map<String, Object>> queryList = (List<Map<String, Object>>) super.jsonToObject(condition, List.class);
        for (Map<String, Object> single : queryList) {
            if ("null".equals(single.get("keywords"))) {
                sb.append(" and ")
                        .append(sqlFormater(single.get("column").toString()))
                        .append(" is null ");
            }
            if ("notnull".equals(single.get("keywords"))) {
                sb.append(" and ")
                        .append(sqlFormater(single.get("column").toString()))
                        .append(" is not null ");
            }
            if ("eq".equals(single.get("keywords"))) {
                sb.append(" and ")
                        .append(sqlFormater(single.get("column").toString()))
                        .append(" = ")
                        .append("'")
                        .append(sqlFormater(single.get("value").toString()))
                        .append("' ");
            }
            if ("numeq".equals(single.get("keywords"))) {
                sb.append(" and ")
                        .append(sqlFormater(single.get("column").toString()))
                        .append(" = ")
                        .append(sqlFormater(single.get("value").toString()))
                        .append(" ");
            }
            if ("neq".equals(single.get("keywords"))) {
                sb.append(" and ")
                        .append(sqlFormater(single.get("column").toString()))
                        .append(" != ")
                        .append("'")
                        .append(sqlFormater(single.get("value").toString()))
                        .append("' ");
            }
            if ("like".equals(single.get("keywords"))) {
                sb.append(" and ")
                        .append(sqlFormater(single.get("column").toString()))
                        .append(" like ")
                        .append(" '%")
                        .append(sqlFormater(single.get("value").toString()))
                        .append("%' ");
            }
            if ("likes".equals(single.get("keywords"))) {
                sb.append(" and ( ");
                List<String> column = (List) single.get("column");
                int index = 0;
                for (String c : column) {
                    if (index != 0) {
                        sb.append(" or ");
                    }
                    sb.append(sqlFormater(c))
                            .append(" like ")
                            .append(" '%")
                            .append(sqlFormater(single.get("value").toString()))
                            .append("%' ");
                    index++;
                }
                sb.append(" ) ");
            }
            if ("likeFront".equals(single.get("keywords"))) {
                sb.append(" and ")
                        .append(sqlFormater(single.get("column").toString()))
                        .append(" like ")
                        .append(" '")
                        .append(sqlFormater(single.get("value").toString()))
                        .append("%' ");
            }
            if ("likeBehind".equals(single.get("keywords"))) {
                sb.append(" and ")
                        .append(sqlFormater(single.get("column").toString()))
                        .append(" like ")
                        .append(" '%")
                        .append(sqlFormater(single.get("value").toString()))
                        .append("' ");
            }
            if ("in".equals(single.get("keywords"))) {
                sb.append(" and ")
                        .append(sqlFormater(single.get("column").toString()))
                        .append(" in ( ");
                List<String> values = (List) single.get("values");
                int index = 0;
                for (String v : values) {
                    if (index != 0) {
                        sb.append(" , ");
                    }
                    sb.append(" '")
                            .append(sqlFormater(v))
                            .append("' ");
                }
                sb.append(" ) ");
            }
            if ("range".equals(single.get("keywords"))) {
                Map<String, Object> vObj = (Map<String, Object>) single.get("value");
                if (!isEmptyStr((String) vObj.get("start"))) {
                    sb.append(" and ")
                            .append(sqlFormater(single.get("column").toString()))
                            .append(" >= '")
                            .append(sqlFormater(vObj.get("start").toString()))
                            .append(" 00:00:00' ");
                }
                if (!isEmptyStr((String) vObj.get("end"))) {
                    sb.append(" and ")
                            .append(sqlFormater(single.get("column").toString()))
                            .append(" < '")
                            .append(sqlFormater(vObj.get("end").toString()))
                            .append(" 23:59:59' ");
                }
            }
            if ("morethan".equals(single.get("keywords"))) {
                sb.append(" and ")
                        .append(sqlFormater(single.get("column").toString()))
                        .append(" >= ")
                        .append(sqlFormater(single.get("value").toString()));
            }
            if ("lassthan".equals(single.get("keywords"))) {
                sb.append(" and ")
                        .append(sqlFormater(single.get("column").toString()))
                        .append(" <= ")
                        .append(sqlFormater(single.get("value").toString()));
            }
        }
        return sb.toString();
    }

	//字段值去除特殊符号,避免sql注入
    private String sqlFormater(String value) {
        value = value.replaceAll("'", "")
                .replaceAll(",", "")
                .replaceAll("=", "")
                .replaceAll(" ", "");
        return value;
    }
}

dao:MGoodMapper.java

package com.core.jjtm.dao;
import com.core.jjtm.dao.page.MybatisPager;
import com.core.jjtm.entity.MGood;
import java.util.List;

public interface MGoodMapper extends MybatisPager {
    List<MGood> select(MGood record);
}

dao继承的接口:MybatisPager.java

因为所有dao接口都要写分页,所以提取出来,所有的dao都继承这个接口。

package com.core.jjtm.dao.page;
import java.util.List;

public interface MybatisPager {
    <T> List<T> selectPage(T record); //分页的接口方法
    <T>Integer selectPageCount(T record); //分页总数的接口方法
}

mapper:MGoodMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.core.jjtm.dao.MGoodMapper">

  <resultMap id="BaseResultMap" type="com.core.jjtm.entity.MGood">
    <id column="id" jdbcType="VARCHAR" property="id" />
    <result column="type" jdbcType="VARCHAR" property="type" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="specs" jdbcType="VARCHAR" property="specs" />
    <result column="imgs" jdbcType="VARCHAR" property="imgs" />
    <result column="storeid" jdbcType="VARCHAR" property="storeid" />
    <result column="fromgoodid" jdbcType="VARCHAR" property="fromgoodid" />
    <result column="unitprice" jdbcType="DECIMAL" property="unitprice" />
    <result column="price" jdbcType="DECIMAL" property="price" />
    <result column="note" jdbcType="VARCHAR" property="note" />
    <result column="crttime" jdbcType="TIMESTAMP" property="crttime" />
    <!-- out start -->
    <result column="count" jdbcType="DECIMAL" property="count" /><!-- 商品数量 -->
    <!-- out end -->
  </resultMap>

  <select id="select" resultMap="BaseResultMap" parameterType="com.core.jjtm.entity.MGood" >
    select  ifnull(sum(b.count),0) as count,
    a.id, a.type, a.storeid, a.fromgoodid, a.crttime,
    if(a.fromgoodid is null,a.storeid,c.storeid) as fromstoreid,
    if(a.fromgoodid is null,d.name,e.name) as fromstorename,
    if(a.fromgoodid is null,a.name,c.name) as name,
    if(a.fromgoodid is null,a.specs,c.specs) as specs,
    if(a.fromgoodid is null,a.imgs,c.imgs) as imgs,
    if(a.fromgoodid is null,a.unitprice,c.unitprice) as unitprice,
    if(a.fromgoodid is null,a.price,c.price) as price,
    if(a.fromgoodid is null,a.note,c.note) as note
    from m_good a
    left join m_good_stock b on b.goodid = a.id
    left join m_good c on c.id = a.fromgoodid
    left join m_store d on d.id = a.storeid
    left join m_store e on e.id = c.storeid
    <where>
      <if test="id != null">
        and a.id = #{id,jdbcType=VARCHAR}
      </if>
      <if test="storeid != null">
        and a.storeid = #{storeid,jdbcType=VARCHAR}
      </if>
      <if test="fromgoodid != null">
        and a.fromgoodid = #{fromgoodid,jdbcType=VARCHAR}
      </if>
      <if test="type != null">
        and a.type = #{type,jdbcType=VARCHAR}
      </if>
      <if test="c != null">
        ${c}
      </if>
    </where>
    group by a.id
    order by a.crttime desc
  </select>

  <select id="selectPage" resultMap="BaseResultMap" parameterType="com.core.jjtm.entity.MGood" >
    select  ifnull(sum(b.count),0) as count,
    a.id, a.type, a.storeid, a.fromgoodid, a.crttime,
    if(a.fromgoodid is null,a.storeid,c.storeid) as fromstoreid,
    if(a.fromgoodid is null,d.name,e.name) as fromstorename,
    if(a.fromgoodid is null,a.name,c.name) as name,
    if(a.fromgoodid is null,a.specs,c.specs) as specs,
    if(a.fromgoodid is null,a.imgs,c.imgs) as imgs,
    if(a.fromgoodid is null,a.unitprice,c.unitprice) as unitprice,
    if(a.fromgoodid is null,a.price,c.price) as price,
    if(a.fromgoodid is null,a.note,c.note) as note
    from m_good a
    left join m_good_stock b on b.goodid = a.id
    left join m_good c on c.id = a.fromgoodid
    left join m_store d on d.id = a.storeid
    left join m_store e on e.id = c.storeid
    <where>
      <if test="storeid != null">
        and a.storeid = #{storeid,jdbcType=VARCHAR}
      </if>
      <if test="type != null">
        and a.type = #{type,jdbcType=VARCHAR}
      </if>
      <if test="c != null">
        ${c}
      </if>
    </where>
    group by a.id
    order by
    <choose>
      <when test="o != null">
        ${o}
      </when>
      <otherwise>
        a.crttime desc
      </otherwise>
    </choose>
    limit ${m} , ${n}
  </select>

  <select id="selectPageCount" resultType="java.lang.Integer" parameterType="com.core.jjtm.entity.MGood" >
    select count(distinct a.id)
    from m_good a
    left join m_good_stock b on b.goodid = a.id
    left join m_good c on c.id = a.fromgoodid
    left join m_store d on d.id = a.storeid
    left join m_store e on e.id = c.storeid
    <where>
      <if test="storeid != null">
        and a.storeid = #{storeid,jdbcType=VARCHAR}
      </if>
      <if test="type != null">
        and a.type = #{type,jdbcType=VARCHAR}
      </if>
      <if test="c != null">
        ${c}
      </if>
    </where>
  </select>
</mapper>
3.3 service,controller访问器代码

service接口:ICrudService.java

package com.core.jjtm.service.local;
import com.core.jjtm.entity.*;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.List;

public interface ICrudService {
    List<MGood> selectMGood(MGood record);
    List<MGood> selectMGoodPage(MGood record);
    Integer selectMGoodPageCount(MGood record);
}

service接口实现类:CrudServiceImpl

package com.core.jjtm.service.local.impl;
import com.core.jjtm.dao.*;
import com.core.jjtm.entity.*;
import com.core.jjtm.service.local.ICrudService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;

@Service
public class CrudServiceImpl implements ICrudService {
	@Autowired
    MGoodMapper mGoodMapper;
    
    @Override
    public List<MGood> selectMGood(MGood record) {
    	//可在此编写其他业务逻辑
        return mGoodMapper.select(record);
    }
    @Override
    public List<MGood> selectMGoodPage(MGood record) {
    	//可在此编写其他业务逻辑
        return mGoodMapper.selectPage(record);
    }
    @Override
    public Integer selectMGoodPageCount(MGood record) {
    	//可在此编写其他业务逻辑
        return mGoodMapper.selectPageCount(record);
    }
}

controller:ManageBaseController.java

package com.core.jjtm.controller.man;
import com.core.jjtm.utils.RouteUtil;

/****基础商户请求****/
@RestController
@RequestMapping("/manbase")
public class ManageBaseController extends RouteUtil {

	/* 分页获取本店商品*/
    @GetMapping(value = "getMyGoodPage")
    public Object getMyGoodPage(HttpServletRequest req, MGood cdt) {
        cdt.setType(TypeDic.GOOD_TYPE_MINE);//商品类型自拥有
        cdt.setStoreid("1001");//假设值-商店id
        Map<String,String> pghr = layuiPager(req);//获取前台layui插件传来的m,n的值。不用layui分页的同学,没有此步,直接将m,n代入就好了
        cdt.setM(pghr.get("m"));
        cdt.setN(pghr.get("n"));
        //以下封装号数据返回前端
        return RSLB().build("list",crudService.selectMGoodPage(cdt),"total",crudService.selectMGoodPageCount(cdt));
    }

	/**
     *layui前端分页插件适配
     **/
    public Map<String, String> layuiPager(HttpServletRequest req) {
        Map<String, String> res = new HashMap<String, String>();
        int page = Integer.parseInt(req.getParameter("page"));
        int limit = Integer.parseInt(req.getParameter("limit"));
        res.put("m", String.valueOf((page - 1) * limit));
        res.put("n", String.valueOf(limit));
        return res;
    }

	/**
     *返回数据封装对象bean
     **/
	public ResultBean RSLB(){
        return new ResultBean();
    }

}

封装类ResultBean.java

package com.core.jjtm.domain;
import org.springframework.stereotype.Component;
import java.util.*;

//自己写的组件一直都这么用,方便封装各种数据返回前台。
@Component
public class ResultBean {
    private Map<String, Object> bean;
    public ResultBean(){
        this.bean = new HashMap<>();
    }
    public ResultBean create(){
        this.bean.clear();
        return this;
    }
    public ResultBean pour(String key,Object obj){
        this.bean.put(key,obj);
        return this;
    }
    public ResultBean Code(Object code){
        this.bean.put("code",code);
        return this;
    }
    public ResultBean Error(Object error){
        this.bean.put("error",error);
        return this;
    }
    public Map<String, Object> build(Object ... ags){
        List<Object> objects = Arrays.asList(ags);
        Iterator<Object> iterator = objects.iterator();
        while(iterator.hasNext()){
            Object next1 = iterator.next();
            if(iterator.hasNext()){
                Object next2 = iterator.next();
                this.bean.put(next1.toString(),next2);
            }
        }
        return this.bean;
    }
    public Map<String, Object> build(){
        return this.bean;
    }
}
3.4 页面代码 (省略其他代码)
<!DOCTYPE html>
<html>
<head>
    <title>门店商品列表</title>
    <!-- 标签省略 -->
    <link rel="stylesheet" href="/jjtm/asset/common/global.css" media="all">
    <link rel="stylesheet" href="/jjtm/layuiadmin/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="/jjtm/layuiadmin/style/admin.css" media="all">     
</head>
<body class="captureMark">

<div class="layui-fluid">
    <div class="layui-row layui-col-space15">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-body">
                    <fieldset class="layui-elem-field">
                        <legend style="font-size: 18px;font-weight: bold">门店商品列表</legend>
                        <div class="layui-field-box">
                            门店产品及总库存,满赠活动、营销活动、联盟交易、推广购买都会扣除库存,创建后不可改价,请按需求增加库存,不要盲目添加。若价格调整,请新建同类产品。
                            数量不足,会自动停止各类有关活动,请及时补充库存。
                        </div>
                    </fieldset>
                    <div class="layui-collapse">
                        <div class="layui-colla-item">
                            <h2 class="layui-colla-title myfilter">检索/筛选
                                <span class="selected"
                                      style="padding:1px 5px;background-color: #FF6666;color:#fff;border-radius: 100%">0</span>
                            </h2>
                            <div class="layui-colla-content">
                                <form class="search-form layui-form" action="" lay-filter="component-form-group">
                                    <div class="layui-row">
                                        <div class="layui-input-inline layui-col-xs12 layui-col-sm12 layui-col-md12">
                                            <label class="layui-form-label">字段检索</label>
                                            <div class="layui-input-block">
                                                <input type="text" name="search" lay-verify="normal" autocomplete="off" placeholder="商品号/名称/描述" maxlength="20"
                                                       class="layui-input">
                                            </div>
                                        </div>
                                        <div class="layui-input-inline layui-col-xs12 layui-col-sm6 layui-col-md6">
                                            <label class="layui-form-label">开始时间</label>
                                            <div class="layui-input-block">
                                                <input type="text" id="date-st" name="date_st"
                                                       placeholder="开始时间(创建时间)"
                                                       autocomplete="off" class="layui-input" readonly>
                                            </div>
                                        </div>
                                        <div class="layui-input-inline layui-col-xs12 layui-col-sm6 layui-col-md6">
                                            <label class="layui-form-label">结束时间</label>
                                            <div class="layui-input-block">
                                                <input type="text" id="date-en" name="date_en"
                                                       placeholder="结束时间(创建时间)"
                                                       autocomplete="off" class="layui-input" readonly>
                                            </div>
                                        </div>
                                        <div class="layui-input-inline layui-col-xs12 layui-col-sm6 layui-col-md6">
                                            <div class="layui-input-block">
                                                <button
                                                        class="layui-btn layui-btn-fluid" lay-submit
                                                        lay-filter="seachdata">开始检索
                                                </button>
                                            </div>
                                        </div>
                                        <div class="layui-input-inline layui-col-xs12 layui-col-sm6 layui-col-md6">
                                            <div class="layui-input-block">
                                                <button
                                                        class="layui-btn layui-btn-primary layui-btn-fluid"
                                                        type="reset">清空
                                                </button>
                                            </div>
                                        </div>
                                    </div>
                                </form>
                            </div>
                        </div>
                    </div>
                    <div style="height:5px;"></div>
                    <table class="layui-hide" id="test-table-page" lay-filter="mytable"></table>
                </div>
            </div>
        </div>
    </div>
</div>
<script type="text/html" id="toolbarDemo">
    <div class="layui-btn-container">
        <button class="layui-btn layui-btn-sm" lay-event="export">导出当前所有数据</button>
        <button class="layui-btn layui-btn-sm layui-btn-normal" lay-event="add"><i
                class="layui-icon layui-icon-addition"></i></button>
    </div>
</script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/2.2.4/jquery.js"></script>
<script src="/jjtm/layuiadmin/layui/layui.js"></script>
<script src="/jjtm/asset/common/global.js"></script>
<script src="/jjtm/asset/common/pcg.js"></script>
<script src="https://cdn.bootcss.com/touchjs/0.2.14/touch.min.js"></script>
<script src="/jjtm/asset/common/capture.js"></script>
<script>
    var _condition = [];
    var _tableIns = null;
    layui.config({
        base: '/jjtm/layuiadmin/' //静态资源所在路径
    }).extend({
        index: 'lib/index' //主入口模块
    }).use(['index', 'table', 'laydate', 'upload', 'form'], function () {
        admin = layui.admin
            , table = layui.table
            , laydate = layui.laydate
            , upload = layui.upload
            , form = layui.form;
        selectPage();//分页查询的方法
        initFilter();//初始化layui的筛选UI
        initSort();//初始化金额列名上的点击排序
    });

    function initFilter() {
        //初始化datepicker
        laydate.render({
            elem: '#date-st'
        });
        laydate.render({
            elem: '#date-en'
        });
        form.on('submit(seachdata)', function (data) {
            console.log(data.field)
            _condition = [];
            var selected = 0;
            if (!GLOBAL.isEmptyStr(data.field.search)) {
                _condition.push({keywords: 'likes', column: ['a.id','a.name','a.note'], value: data.field.search});
                selected++;
            }
            !GLOBAL.isEmptyStr(data.field.date_st) ? selected++ : null;
            !GLOBAL.isEmptyStr(data.field.date_en) ? selected++ : null;
            _condition.push({
                keywords: 'range',
                column: 'a.crttime',
                value: {start: data.field.date_st, end: data.field.date_en}
            });
            $('.layui-colla-title .selected').html(selected);
            selectPage();
            $('.layui-colla-title.myfilter').click();
            return false; //阻止表单跳转。如果需要表单跳转,去掉这段即可。
        });
    }

    function initSort() {
        //自主排序
        table.on('sort(mytable)', function (obj) {
            if (obj.type != null) {
                _tableIns.reload({
                    initSort: obj //记录初始排序,如果不设的话,将无法标记表头的排序状态。
                    , where: { //请求参数(注意:这里面的参数可任意定义,并非下面固定的格式)
                        orderstr: '(\'\'+a.' + obj.field + ') ' + obj.type
                    }
                });
            }
        });
    }

    function selectPage() {
        _tableIns = table.render({
            elem: '#test-table-page',
            cols: [[
                {title: '序号', type: 'numbers'}
                , {field: 'id', title: '商品号'}
                , {field: 'name', title: '名称'}
                , {field: 'specs', title: '规格单位'}
                , {
                    field: 'count', title: '库存数量', templet: function (d) {
                        return d.count == null || d.count == 0 ? '<span style="color:#FF6666">0</span>' : d.count;
                    }
                }
                , {
                    title: '图片', templet: function (d) {
                        return tableImg(d.imgs);
                    }
                }
                , {field: 'unitprice', title: '采购价格(元)', sort: true}
                , {field: 'price', title: '推广价格(元)', sort: true}
                , {field: 'note', title: '产品介绍'}
                , {field: 'crttime', title: '创建时间'}
                , {
                    title: '操作', width:150, templet: function (d) {
                        var btnStr = '';
                        btnStr += '<button class="layui-btn layui-btn-sm layui-btn-danger" lay-event="addCount">维护</button>';
                        btnStr += '<button class="layui-btn layui-btn-sm" lay-event="lookStock">流水</button>';
                        return btnStr;
                    }
                }
            ]],
            autoSort: false,
            url: _ctx + 'manbase/getMyGoodPage',
            method: 'get',
            where: {c: JSON.stringify(_condition)},//此处传输筛选sql,分页参数mn由插件自动上传,须在后台处理后接收
            parseData: function (res) { //res 即为原始返回的数据
                console.log(res)
                return {
                    "code": 0, //解析接口状态
                    "msg": '请求成功', //解析提示文本
                    "count": res.total, //解析数据长度
                    "data": res.list //解析数据列表
                };
            },
            defaultToolbar: ['filter', 'print'],
            toolbar: '#toolbarDemo',
            limit: 10,
            limits: [10, 20],
            page: true,
            loading: true,
            title: '门店商品导出记录' + GLOBAL.createDateStr(true),
            text: {
                none: '对不起,没有查到相关数据'
            }
        });
    }

</script>
</body>
</html>

前台不用layui也可以,这里只分享后台的代码逻辑思路。

总结:

mysql数据库的分页,不管使用何种分页插件,后台总是使用了两条查询语句:

一句查分页数据
一句查数据总条数。

多条件筛选,因为筛选条件可能千变万化,所以拼接sql是最方便的办法。
在能保证数据安全和前后端低耦合的情况下,是可以使用拼接sql这种老方法的。

分页插件以前公司项目也在用,但我总觉得只是为用而用,很多插件的特色,几乎都没用到。

所以我的理解是,使用各种插件前,应该非常了解这个插件的功能特色。

在自写代码满足不了项目需求时,再去选择这些插件。





-end
有错误请指出,有问题请留言,谢谢

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值