JAVA-WEB基础

高级查询

2020-05-22  本文已影响0人  superNeil

分页和过滤查询

流程图 :

高级查询.jpg
1 设计和原理分析
image-20200521230058307.png
前面我们已经讲过分页查询了 , 接下来我们讲讲 过滤查询 .

思路 : 从后台开始写 , 写好测试 , 测试成功 ; 开始写前台 .

这里我们需要 MyBatis动态sql语句

为了解决在 xml 中拼接 SQL 的问题,此处需要来学习 MyBatis 的动态 SQL

<where> 和<if> 标签的配合使用

<select id="queryCount" resultType="int">
        SELECT count(*) FROM t_armoire
        <where>
            <if test="keyword!=null and keyword!=''">
                AND supplier LIKE concat('%',#{keyword},'%')
            </if>
            <if test="minPrice!=null">
                AND price >= #{minPrice}
            </if>
            <if test="maxPrice!=null">
                AND price &lt;= #{maxPrice}
            </if>
        </where>
    </select>
    <select id="queryResult" resultType="armoire">
        SELECT * FROM t_armoire
        <where>
            <if test="keyword!=null and keyword!=''">
                AND supplier LIKE concat('%',#{keyword},'%')
            </if>
            <if test="minPrice!=null">
                AND price >= #{minPrice}
            </if>
            <if test="maxPrice!=null">
                AND price &lt;= #{maxPrice}
            </if>
        </where>
        limit #{beginIndex},#{pageSize}
    </select>

首先 , 我们现在需要用户传入的 过滤条件封装成对象 ArmoireQueryObject, 去继承 QueryObject ,这样我们通过 ArmoireQueryObject就可以获取用户传来的所有参数 .

@ToString
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class ArmoireQueryObject extends QueryObject {
    //用户传来   高级查询 的参数
    //1. 关键字  2. 最小值  3. 最大值
    private String keyword;
    private Integer minPrice;
    private Integer maxPrice;
    //继承  这样 其实已经有  5+2 + getBegin 数据了
}

list.jsp 操作步骤 添加在 form标签中

<p align="center">                               //这里是value 是回显,可以先不管
        关键字:<input type="text" name="keyword" value="${aq.keyword}">
        价格:<input type="number" name="minPrice" value="${aq.minPrice}"> ~ <input type="number" name="maxPrice" value="${aq.maxPrice}">
        <input type="submit" value="提交"></p>

注意:一般的,为了避免不必要的麻烦,让字段名称和表单中的请求参数名称相同 .

DAO

public interface IArmoireDAO {
    //高级查询 总条数
    int queryCount(ArmoireQueryObject aq);
    //高级查询 页面结果集
    List<?>queryResult(ArmoireQueryObject aq);
}
public class ArmoireDAOImpl implements IArmoireDAO {
    @Override
    public int queryCount(ArmoireQueryObject aq) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        int count = sqlSession.selectOne("cn.wolfcode.amis.mapper.ArmoireMapper.queryCount", aq);
        sqlSession.close();
        return count;
    }

    @Override
    public List<?> queryResult(ArmoireQueryObject aq) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        List<?>list = sqlSession.selectList("cn.wolfcode.amis.mapper.ArmoireMapper.queryResult", aq);
        sqlSession.close();
        return list;
    }
}

注意 ; MyBatisUtil 自己去拿 . 算了 还是写给你吧 (这是我封装好的工具类 , 拿去用吧 害 !)

public class MyBatisUtil {
    private MyBatisUtil() {
        //私有化构造器
    }
    static SqlSessionFactory factory = null;
    static {
        try {
            factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static SqlSession getSqlSession() {
        return factory.openSession();
    }
}

还有后面 service要用的工具类 , 方便点 , 统统给你. StringUtil

public class StringUtil {
    private StringUtil(){
        //私有化构造器
    }
    //判空
    public static boolean hasLength(String str){
        return str!=null && !"".equals(str.trim());
    }
}

后台这样其实就已经写好了 , 测试下吧 . 成功继续...

想想我们 需要给前台 返回什么数据 ??? 之前分页查询已经说过了 .

两输 , 两查 , 三计算 封装成对象 .

@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@ToString
public class PageResult {
    //存 2输  2查 3计算
    private int currentPage;
    private int pageSize;
    //2查
    private int totalCount;
    private List<?> listResult;
    //3 计算  上一页 下一页 总页数
    private int totalPage;
    private int prevPage;
    private int nextPage;
    //自定义构造器
    public PageResult(int currentPage,int pageSize,int totalCount,List<?> listResult){
        this.currentPage=currentPage;
        this.pageSize=pageSize;
        this.totalCount=totalCount;
        this.listResult=listResult;
        this.totalPage=totalCount%pageSize==0?totalCount/pageSize:totalCount/pageSize+1;
        this.prevPage=currentPage>1?currentPage-1:1;
        this.nextPage=currentPage<totalPage?currentPage+1:totalPage;
    }
}

我们看看service 层 (调用方法: 参数: 前台的数据传来封装到 ArmoireQueryObject 对象中)返回一个前台需要的 所有数据 PageResult对象过去 .

public interface IArmoireService {
    //业务层
    PageResult query(ArmoireQueryObject aq);
}

简单吧 ! ! !

有了接口 , 就要去实现吧 , 不然要它何用 ?

实现 :

public class ArmoireServiceImpl implements IArmoireService {
    @Override
    public PageResult query(ArmoireQueryObject aq) {
        IArmoireDAO dao=new ArmoireDAOImpl();
        List<?> list = dao.queryResult(aq);
        int count = dao.queryCount(aq);
        if(count==0){
            //如果为0 , 返回空集
            return new PageResult(aq.getCurrentPage(),aq.getPageSize(),0,new ArrayList<>());
        }
        return new PageResult(aq.getCurrentPage(),aq.getPageSize(),count,list);
    }
}

真棒 , 都看到这里了 , 那我们是不是应该做啥事呢 ? 肯定是测试呀 !(还用想吗, 一天天的啥也不是啊哈! ! !)

测试成功 ...

我们开始写 servlet吧 快结束了 .

@WebServlet("/arm")
public class ArmoireServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        IArmoireService service=new ArmoireServiceImpl();
        ArmoireQueryObject aq = new ArmoireQueryObject();

        //分页查询 : 用户输入
        String strCurrentPage = req.getParameter("currentPage");
        if(StringUtil.hasLength(strCurrentPage)){
            Integer currentPage = Integer.valueOf(strCurrentPage);
            aq.setCurrentPage(currentPage);
        }
        String strPageSize = req.getParameter("pageSize");
        if(StringUtil.hasLength(strPageSize)){
            Integer pageSize = Integer.valueOf(strPageSize);
            aq.setPageSize(pageSize);
        }

        //过滤查询
        String keyword = req.getParameter("keyword");
        aq.setKeyword(keyword);
        String strMinPrice = req.getParameter("minPrice");
        if(StringUtil.hasLength(strMinPrice)){
            Integer minPrice = Integer.valueOf(strMinPrice);
            aq.setMinPrice(minPrice);
        }
        String strMaxPrice = req.getParameter("maxPrice");
        if(StringUtil.hasLength(strMaxPrice)){
            Integer maxPrice = Integer.valueOf(strMaxPrice);
            aq.setMaxPrice(maxPrice);
        }


        PageResult list = service.query(aq);
        //共享
        req.setAttribute("aq",aq);//回显数据 这里有 关键字 最大 最小 +2
        req.setAttribute("list",list);//返回 页面需要的 结果数据
        //跳转
        req.getRequestDispatcher("/list.jsp").forward(req,resp);
    }
}

总算写好了 , 那我们要干啥啊 , 问我 ? ? ? 把它装上 jsp页面上 .

看着有点复杂 , 其实静下心来 , 看看 , 其实 JAVA 也就那样 . 其实 学习 JAVA 也是一种修行哈 , 越努力越幸运 , 加油 !

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>信息管理系统</title>
    <script>
        function onChange() {
            document.forms[0].submit();
        }

        function goPage(pageNum) {
            document.getElementById("currentPageId").value = pageNum;
            document.forms[0].submit();
        }
    </script>
</head>
<body>
<h3 align="center">货品信息查询系统</h3>
<form action="/arm">
    <p align="center">
        关键字:<input type="text" name="keyword" value="${aq.keyword}">
        价格:<input type="number" name="minPrice" value="${aq.minPrice}"> ~ <input type="number" name="maxPrice" value="${aq.maxPrice}">
        <input type="submit" value="提交"></p>
    <table border="1" cellpadding="0" cellspacing="0" style="width: 80%" align="center">
        <tr>
            <th>序号</th>
            <th>出产商</th>
            <th>类型</th>
            <th>价格</th>
        </tr>
        <c:forEach items="${list.listResult}" var="arm" varStatus="vs">
            <tr>
                <td>${vs.count}</td>
                <td>${arm.supplier}</td>
                <td>${arm.type}</td>
                <td>${arm.price}</td>
            </tr>
        </c:forEach>
        <tr align="center">
            <td colspan="4">
                <a href="#" onclick="goPage(1)">首页</a>
                <a href="#" onclick="goPage(${list.prevPage})">上一页</a>
                <a href="#" onclick="goPage(${list.nextPage})">下一页</a>
                <a href="#" onclick="goPage(${list.totalPage})">末页</a>
                当前${list.currentPage}页
                共${list.totalPage}页
                跳转<input type="number" name="currentPage" onchange="onChange()" style="width: 60px"
                         value="${list.currentPage}" id="currentPageId">页
                每页显示
                <select name="pageSize">
                    <option value="3" ${list.pageSize==3?'selected':''}> 3</option>
                    <option value="5" ${list.pageSize==5?'selected':''}> 5</option>
                    <option value="8" ${list.pageSize==8?'selected':''}> 8</option>
                </select>
                条数据
            </td>
        </tr>
    </table>
</form>
</body>
</html>
上一篇 下一篇

猜你喜欢

热点阅读