SSM框架项目【米米商城】69-93:多条件查询

开始时间:2022-03-07
课程链接:米米商城

Ajax多条件查询

我们把可以看到查询条件有4个
在这里插入图片描述
创建一个ProductInfoVO类用于存放这四个参数

package BUPT.pojo.VO;

public class ProductInfoVO {
    //商品名称
    private String pname;
    //商品类型
    private Integer typeid;
    //最低价格
    private Integer lprice;
    //最高价格
    private Integer hprice;
	//getter and setter
	//toString();
	//constructor

然后写Mapper接口,用于设置多条件查询
接口里

    //多条件查询
    List<ProductInfo> selectCondition(ProductInfoVO vo);

Mapper配置文件里

<select id="selectCondition" parameterType="BUPT.pojo.VO.ProductInfoVO" resultMap="BaseResultMap">
        select
        <!-- 为了避免出错,就不用*号了,这里的refid,读取的是所有的字段名-->
        <include refid="Base_Column_List"></include>
        from product_info
        <where>
            <if test="pname!=null and pname!=''">
                and p_name like '%${pname}%'
            </if>
            <!--默认复选框不选择时 typeid的值是-1-->
            <if test="typeid!=null and typeid!=-1">
                and type_id = #{typeid}
            </if>
            <if test="(lprice!=null and lprice!='') and (hprice==null or hprice=='')">
                and p_price &gt;= #{lprice}
            </if>
            <if test="(hprice!=null and hprice!='') and (lprice==null or lprice=='')">
                and p_price &lt;= #{hprice}
            </if>
            <if test="(hprice!=null and hprice!='') and (lprice!=null and lprice!='')">
                <!-- between and都是闭区间-->
                and p_price between #{lprice} and #{hprice}
            </if>
        </where>
        order by p_id desc
    </select>

这样就把四个框里的数据都读取到了
有多少叠加多少
为了确保我们写的SQL语句没问题
我们需要写一个测试类

package BUPT.Test;

import BUPT.mapper.ProductInfoMapper;
import BUPT.pojo.ProductInfo;
import BUPT.pojo.VO.ProductInfoVO;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;
//@RunWith(SpringJUnit4ClassRunner.class),让测试运行于Spring测试环境
@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration : 加载配置文件
@ContextConfiguration(locations = {"classpath:applicationContext_dao.xml", "classpath:applicationContext_service.xml"})
public class MyTest {
    @Autowired
    ProductInfoMapper mapper;

    @Test
    public void MyselectCondition() {
        ProductInfoVO vo = new ProductInfoVO();
        vo.setLprice(500);
        vo.setHprice(1700);
        List<ProductInfo> list = mapper.selectCondition(vo);
        for (ProductInfo pro : list
        ) {
            System.out.println(pro);
        }
    }
}

我们发现测试没问题,能够实现多条件联合查询
此时我们来完成product.jsp里面功能的实现
在条件搜索框所处的导航栏部分中写上

    <div id="condition" style="text-align: center">
        <form id="myform">
            商品名称:<input name="pname" id="pname">&nbsp;&nbsp;&nbsp;
            商品类型:<select name="typeid" id="typeid">
            <option value="-1">请选择</option>
            <c:forEach items="${typeList}" var="pt">
                <option value="${pt.typeId}">${pt.typeName}</option>
            </c:forEach>
        </select>&nbsp;&nbsp;&nbsp;
            价格:<input name="lprice" id="lprice">-<input name="hprice" id="hprice">
            <input type="button" value="查询" onclick="condition()">
        </form>
    </div>

然后补充condition方法

function condition() {
        //取出查询条件
        var pname = $("#pname").val();
        var typeid = $("#typeid").val();
        var lprice = $("#lprice").val();
        var hprice = $("#hprice").val();
        $.ajax({
            url: "${pageContext.request.contextPath}/prod/condition.action",
            data: {"pname": pname, "typeid": typeid, "lprice": lprice, "hprice": hprice},
            type: "post",
            success: function () {
                //重新加载分页显示的组件table
                $("#table").load("http://localhost:8080/mimi_SSM/admin/product.jsp #table");
            }
        })
    }

此时我们进行测试
在这里插入图片描述
我们会发现在加载页面中,即使查询了数据,还是没有页面刷新
这是因为我们的 #table标签中,用的是info.list,而不是我们刚刚上传的list
但从控制台的输出信息,我们是能判断已经成功进行了检索
在这里插入图片描述
那如果把#table里面的

<c:forEach items="${info.list}" var="p">

改为list,是可以得到检索后的结果,但是这样初始进去的时候是没有显示的,且检索后的结果是不能实现分页的。
为了改善这一情况,我们可以考虑将刚刚设置的vo类,增加分页功能
在ProductInfo类中添加属性

    //设置页码
    private Integer page = 1;

且进一步的,添加多条件分页查询的接口

PageInfo splitPageVO(ProductInfoVO vo, int PageSize);

以及实现类

    @Override
    public PageInfo<ProductInfo> splitPageVO(ProductInfoVO vo, int PageSize) {
        PageHelper.startPage(vo.getPage(), PageSize);
        ProductInfoExample example = new ProductInfoExample();

        //设置排序 按主键大小来排
        //select * from product_info order by p_id desc;
        example.setOrderByClause("p_id desc");
        List<ProductInfo> list = productInfoMapper.selectCondition(vo);
        //将查到的集合封装金pageInfo对象中
        //给了一个list后就封装到pageInfo里面
        PageInfo<ProductInfo> pageInfo = new PageInfo<>(list);
        return pageInfo;
    }

目的在于能把pageInfoVO的信息都传出去

然后书写action

@ResponseBody
    @RequestMapping("/condition")
    public void condition(ProductInfoVO vo, HttpSession session) {
        List<ProductInfo> list = productInfoService.selectCondition(vo);
        session.setAttribute("list", list);
    }

这样写的话,我们的多条件查询分页还是没有实现
因为Ajax的翻页处理中并没有拿到vo数据
所以需要改造Ajax翻页处理

//Ajax翻页处理
    @ResponseBody
    @RequestMapping("/ajaxSplit")
    public void ajaxSplit(ProductInfoVO vo, HttpSession session) {
        PageInfo info = productInfoService.splitPageVO(vo, PAGE_SIZE);
        //刷新时session中携带的info
        session.setAttribute("info", info);
    }

这样在有条件时就出有条件的结果,没有条件时,当做条件为空的有条件结果
那么我们在product.jsp中写的condition函数,就不能再和/condition进行匹配了,而是要和改造后的/ajaxSplit匹配

function condition() {
...
            url: "${pageContext.request.contextPath}/prod/ajaxSplit.action",
...

此时进行测试
在这里插入图片描述

但是,我们新的问题又来了,在检索了有超过一页数据的情况下
在这里插入图片描述
一旦通过导航条跳转了页面,那么他就清空了我们的查询语句,这是因为我们写分页Ajax的时候

function ajaxsplit(page)

传的参数data是一个page,没有带上多条件

我们要对ajaxsplit进行改造
让其带上多参数

function ajaxsplit(page) {
        //取出查询条件
        var pname = $("#pname").val();
        var typeid = $("#typeid").val();
        var lprice = $("#lprice").val();
        var hprice = $("#hprice").val();

        //异步ajax分页请求
        $.ajax({
            url: "${pageContext.request.contextPath}/prod/ajaxSplit.action",
            data: {"page": page, "pname": pname, "typeid": typeid, "lprice": lprice, "hprice": hprice},
            type: "post",
            success: function () {
                //重新加载分页显示的组件table
                $("#table").load("http://localhost:8080/mimi_SSM/admin/product.jsp #table");
            }
        })
    };

这样一来就实现了翻页依然保留多条件的查询

如果没有符合条件的商品,我们也要给出一个提示
在这里插入图片描述
这也是在我们的table div分块中写好了的

<c:choose>
    <c:when test="${info.list.size()!=0}"...>
    <c:otherwise>
        <div>
            <h2 style="width:1200px; text-align: center;color: orangered;margin-top: 100px">暂时没有符合条件的商品!</h2>
        </div>
    </c:otherwise>
</c:choose>

更新页面拼接条件的提交

当我们查询到结果后,再修改某一个商品的信息,
或者是我们先在第三页停留,查询到信息后,
都会跳转回第一页,这会影响用户体验。
能不能查询之后,之前是第几页,就停留在第几页呢

所以我们应该想到,我们之前刷新页面是走的哪一个方法

@RequestMapping("/split")
    public String split(HttpServletRequest request) {
    }

这里面我们加载的都是第一页,那我们需要加载到当前页
当前页的信息我们可以在myupdate里面顺着VO对象带过来(放到session里面)vo的getpage是能得到当前的页码
因此写成

   //实现编辑功能时能加载该字段所有的数据,进行初始化,实现数据的呈现
    @RequestMapping("/myupdate")
    public String myshow(int pid, ProductInfoVO vo, HttpServletRequest request, HttpSession session) {
        saveFileName = "";
        //获取商品信息
        ProductInfo info = productInfoService.getByID(pid);
        request.setAttribute("prod", info);
        //将多条件及页码放入session,更新处理结束后读取条件和页码
        session.setAttribute("prodVo", vo);
        return "update";
    }

接着重写

@RequestMapping("/split")
//显示更新后的当前页的五条记录
    @RequestMapping("/split")
    public String split(HttpServletRequest request) {
        PageInfo info = null;
//拿到VO对象
        Object vo = request.getSession().getAttribute("prodVo");
        if (vo != null) {
            info = productInfoService.splitPageVO((ProductInfoVO) vo, PAGE_SIZE);
            //用了就把ProdVo丢了,防止影响后面的数据
            request.getSession().removeAttribute("prodVo");
        } else {
            info = productInfoService.splitPage(1, PAGE_SIZE);
        }
        //这里setAttribute的name是根据前端来的,统一变量名
        request.setAttribute("info", info);
        return "product";
    }

我们再来完善product.jsp页面
写编辑按钮,我们之前只传了一个pId,这里在补充传上info.pageNum

<td>
    <button type="button" class="btn btn-info "
            onclick="one(${p.pId},${info.pageNum})">编辑
    </button>
    <button type="button" class="btn btn-warning" id="mydel"
            onclick="del(${p.pId})">删除
    </button>
</td>

完善这里的one方法

function one(pid, page) {
        //取出查询条件
        var pname = $("#pname").val();
        var typeid = $("#typeid").val();
        var lprice = $("#lprice").val();
        var hprice = $("#hprice").val();
        //实现,点击”编辑“按钮时,向服务器提交请求,传递商品id,这里的pid是我们前面ProductInfoAction中写的参数名,同时传上VO的几个属性值
        var str = "?pid=" + pid + "&page=" + page + "&pname="+pname + "&typeid=" + typeid + "&lprice=" + lprice + "&hprice=" + hprice;
        location.href = "${pageContext.request.contextPath}/prod/myupdate.action" + str;
    }

现在来看看效果
更新了小米Pro的数量
在这里插入图片描述
依然停留在当前页面

同样的,我们想要实现多条件下,多个商品或者单个商品删除后,依然停留在当前页面

删除后停留当前页面

要想停留当前页面,我们还是要先获取到ProductInfoVO对象
那么我们的删除.action,就要有这个值
这个值怎么来的呢?是从product.jsp中携带参数过来的
我们观察到上面编辑更新后停留在当前页面,走的是

<td>
    <button type="button" class="btn btn-info "
            onclick="one(${p.pId},${info.pageNum})">编辑
    </button>
    <button type="button" class="btn btn-warning" id="mydel"
            onclick="del(${p.pId},${info.pageNum})">删除
    </button>
</td>

因此,我们在删除(这里的删除时单页删除)就需要携带info.pageNum
同理,批量删除也是如此

<input type="button" class="btn btn-warning" id="btn1"
       value="批量删除" onclick="deleteBatch(${info.pageNum})">

由于补充了这一个参数,因此要更新好对应的方法,注意传的data要把那几个多条件添加进去
单页删除

function del(pid, page) {

        if (confirm("您确定删除吗?")) {
            //取出查询条件
            var pname = $("#pname").val();
            var typeid = $("#typeid").val();
            var lprice = $("#lprice").val();
            var hprice = $("#hprice").val();
            $.ajax({
                url: "${pageContext.request.contextPath}/prod/delete.action",
                type: "post",
                data: {"pid": pid, "page": page, "pname": pname, "typeid": typeid, "lprice": lprice, "hprice": hprice},
                dataType: "text",
                success: function (msg) {
                    alert(msg);
                    $("#table").load("http://localhost:8080/mimi_SSM/admin/product.jsp #table")
                }
            })
        }
    }

批量删除

  //批量删除
    function deleteBatch(page) {

        //取得所有被选中删除商品的pid
        var deleteBatchChecks = $("input[name=ck]:checked");
        var str = "";
        var pid = "";
        if (deleteBatchChecks.length == 0) {
            alert("请选择将要删除的商品!");
        } else {
            // 有选中的商品,则取出每个选 中商品的ID,拼提交的ID的数据
            if (confirm("您确定删除" + deleteBatchChecks.length + "条商品吗?")) {
                //取出查询条件
                var pname = $("#pname").val();
                var typeid = $("#typeid").val();
                var lprice = $("#lprice").val();
                var hprice = $("#hprice").val();
                //拼接ID
                $.each(deleteBatchChecks, function () {

                    pid = $(this).val(); //22 33

                    //进行非空判断
                    if (pid != null)
                        str += pid + ",";  //22,33,44,
                    //这里的拼接不影响后面,因为传过去转为数据的时候
                    //是转成[22,33,44]的
                });
                $.ajax({
                    url: "${pageContext.request.contextPath}/prod/deleteBatch.action",
                    //拼好的主键id
                    data: {
                        "pids": str,
                        "pid": pid,
                        "page": page,
                        "pname": pname,
                        "typeid": typeid,
                        "lprice": lprice,
                        "hprice": hprice
                    },
                    type: "post",
                    dataType: "text",
                    success: function (msg) {
                        alert(msg);
                        $("#table").load("http://localhost:8080/mimi_SSM/admin/product.jsp #table")
                    }
                })
            }
        }
    }

由于无论是单页删除还是批量删除,都会走

"/deleteAjaxSplit"

这一个action,那么我们就可以改造他使其能处理ProductInfoVO对象

//加了这个注解,表示最后要从这里进行返回
    @ResponseBody
    @RequestMapping(value = "/deleteAjaxSplit", produces = "text/html;charset=UTF-8")
    public Object deleteAjaxSplit(HttpServletRequest request) {
        PageInfo pageInfo = null;
        Object vo = request.getSession().getAttribute("deleteProdVO");
        //取得当前页的数据,删除后返回到当前页
        if (vo != null) {
            pageInfo = productInfoService.splitPageVO((ProductInfoVO) vo, PAGE_SIZE);
            request.getSession().removeAttribute("deleteProdVO");
        } else {
            pageInfo = productInfoService.splitPage(1, PAGE_SIZE);
        }
        request.getSession().setAttribute("info", pageInfo);
        return request.getAttribute("msg");
    }

而传过去,又得通过各自的action
单个删除

@RequestMapping("/delete")
    public String delete(int pid, ProductInfoVO vo, HttpServletRequest request) {
        int num = -1;
        try {
            num = productInfoService.delete(pid);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (num > 0) {
            request.setAttribute("msg", "删除成功");
            //删除成功才需要跳转到删除后的分页
            request.getSession().setAttribute("deleteProdVO", vo);
        } else {
            request.setAttribute("msg", "删除失败");
        }
        //删除结束后跳到分页显示
        return "forward:/prod/deleteAjaxSplit.action";
    }

批量删除

@RequestMapping("/deleteBatch")
    public String deleteBatch(String pids, ProductInfoVO vo,HttpServletRequest request) {
        String[] ps = pids.split(",");

        try {
            //将字符串转为字符数组,再放进批量删除方法里面
            int num = productInfoService.deleteBatch(ps);
            if (num > 0) {
                request.setAttribute("msg", "批量删除成功");
                //删除成功才需要跳转到删除后的分页
                request.getSession().setAttribute("deleteProdVO", vo);
            } else {
                request.setAttribute("msg", "批量删除失败");
            }
        } catch (Exception e) {
            request.setAttribute("msg", "当前商品不可删除");
        }
        return "forward:/prod/deleteAjaxSplit.action";
    }

测试一下
批量删除
在这里插入图片描述
在这里插入图片描述
单个删除
在这里插入图片描述
在这里插入图片描述
结束时间:2022-03-08

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值