美文网首页
mybatis动态条件查询及数据库数据的分页查询实现

mybatis动态条件查询及数据库数据的分页查询实现

作者: 黎涛note | 来源:发表于2019-10-24 22:01 被阅读0次

一、需求分析


1.对于前端页面为多个条件进行检索的情况,查询条件个数不确定的情况,可使用<where>元素。如下:
<select id="id" parameterType=""resultType="">
    SELECT xxx... FROM goods t
    <where>
      <if test="name != null">
          col_name like #{name}
      </if>
      <if test="value>0">
          AND col_name > #{value}
      </if>
    </where>
</select>
<where>元素会进行判断,如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以AND 或OR 开头,它会剔除掉AND或OR。

2.对于检索到的数据,想通过分页进行显示,但是上一次的检索条件在下一次进行翻页时,上一个页面request对象会自动销毁,即将检索条件存入request对象中,也是拿不到数据,原因是翻页后的req对象和前一页的req对象是两个不同的对象,所以必须通过session对象进行存取,将检索条件放入会话对象session中,翻页时通过session对象获取检索条件,查询数据库,进行翻页显示。

3.通过获取用户输入的参数,将参数封装成Map对象,通过将Map对象存入,检索数据。

二、【示例】根据产品的类别、名称、价格范围检索产品


1.jsp页面,前端业务

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>商品检索</title>
</head>
<body>
    <form action="/mybatis_demo1/prdServlet?flag=search" method="post">
          名称:<input type="text" name="prdName"/><br/>
            <select name="typeId">
                <option value="0">请选择商品类别</option>
                <c:if test="${not empty typeList }">
                         <c:forEach items="${typeList}" var="type">
                                <option value="${type.typeId }">${type.typeName } </option>
                         </c:forEach>
                </c:if>
            </select><br/>
          价格范围:<input type="text" name="lowPrice"/>~<input type="text" name="highPrice"/><br/>
            <input type="submit" value="检索"/>
    </form>
    <hr/>
    <c:if test="${not empty prdList }">
        <table>
            <c:forEach items="${prdList }" var="prd">
                <tr>
                    <td>${prd.prdId}</td>
                    <td>${prd.typeId}</td>
                    <td>${prd.prdName}</td>
                    <td>${prd.price}</td>
                    <td>${prd.desc}</td>
                </tr>
            </c:forEach>
        </table>
        当前页:${current} &nbsp; 总页码:${pageCount} &nbsp;&nbsp;
        <c:if test="${current==1}">上一页</c:if> <c:if test="${current>1}"><a href="/mybatis_demo1/prdServlet?flag=change&current=${current }&dir=pre">上一页</a></c:if>&nbsp;&nbsp;
        <c:if test="${current==pageCount}">下一页</c:if><c:if test="${current<pageCount}"><a href="/mybatis_demo1/prdServlet?flag=change&current=${current }&dir=next">下一页</a></c:if>
    </c:if>
</body>
</html>

2.servlet 控制层处理

package com.xixi.demo.servlet;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.sun.javafx.collections.MappingChange.Map;
import com.xixi.demo.common.Constants;
import com.xixi.demo.service.ProductService;
import com.xixi.demo.service.ProductTypeService;
import com.xixi.demo.vo.ProductInfo;
import com.xixi.demo.vo.ProductTypeInfo;

@WebServlet(urlPatterns="/prdServlet")
public class ProductServlet extends BaseServlet {
    
    private ProductService productService = new ProductService();
    private ProductTypeService productTypeService = new ProductTypeService();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
        //设置请求的编码类型
        req.setCharacterEncoding("utf-8");
        //获取请求参数
         String flag = req.getParameter("flag");
         
         if("list".equals(flag)){//获取产品列表
             List<ProductInfo> prdList = this.productService.getAllProducts();
             req.setAttribute("prdList", prdList);
             req.getRequestDispatcher("/prd/prd_list.jsp").forward(req, resp);
         }else if("preAdd".equals(flag)){
             //获取商品所有类别
            List<ProductTypeInfo> typeList = this.productTypeService.getAllTypes();
            req.setAttribute("typeList", typeList);
            req.getRequestDispatcher("/prd/prd_add.jsp").forward(req, resp);
         }else if("preSearch".equals(flag)){
             //获取商品所有类别
             List<ProductTypeInfo> typeList = this.productTypeService.getAllTypes();
             req.setAttribute("typeList", typeList);
             req.getRequestDispatcher("/prd/prd_search.jsp").forward(req, resp);
         }else if("change".equals(flag)){
            @SuppressWarnings("unchecked")
            HashMap<String, Object> cond = (HashMap<String, Object>) req.getSession().getAttribute(Constants.SESSION_SEARCH_COND_KEY);
             int pageNum = 1;
             Integer current = super.getParameterValue(req, "current", Integer.class);
            //获取总页数
            int pageCount = this.productService.getPageCount(cond); 
            if(current != null){
                pageNum = current;
                String dir = super.getParameterValue(req, "dir", String.class);
                if("pre".equals(dir)){
                    pageNum--;
                }else{
                    pageNum++;
                }
                if(pageNum<1)
                    pageNum=1 ;
                if(pageNum>pageCount)
                    pageNum=pageCount;
            }
            req.getSession().setAttribute(Constants.SESSION_SEARCH_COND_KEY, cond);
             //获取商品所有类别
            List<ProductTypeInfo> typeList = this.productTypeService.getAllTypes();
            req.setAttribute("typeList", typeList);

            req.setAttribute("pageCount", pageCount);
            //查询到的商品信息
            List<ProductInfo> prdList = this.productService.search(cond, pageNum);
            req.setAttribute("prdList", prdList);
             
            req.setAttribute("current", pageNum );
            req.getRequestDispatcher("/prd/prd_search.jsp").forward(req, resp);
         }

    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String flag = req.getParameter("flag");
        if("add".equals(flag)){
            String prdName = req.getParameter("prdName");
            Integer typeId = super.getParameterValue(req, "typeId", Integer.class);
            String desc = req.getParameter("desc");
            Float price = super.getParameterValue(req, "price", Float.class);
            
            ProductInfo info = new ProductInfo();
            info.setPrdName(prdName);
            if(typeId>0){
                info.setTypeId(typeId);
            }
            info.setDesc(desc);
            info.setPrice(price);
            boolean result = this.productTypeService.saveInfo(info);
            req.setAttribute("msg", result ? "success!" : "failure!");
            List<ProductTypeInfo> typeList = this.productTypeService.getAllTypes();
            req.setAttribute("typeList", typeList);
            req.getRequestDispatcher("/prd/prd_add.jsp").forward(req, resp);
        }else if("search".equals(flag)){
            String prdName = super.getParameterValue(req, "prdName", String.class);
            Integer typeId = super.getParameterValue(req, "typeId", Integer.class);
            Float lowPrice = super.getParameterValue(req, "lowPrice", Float.class);
            Float highPrice = super.getParameterValue(req, "highPrice", Float.class);
            
            HashMap<String, Object> condition = new HashMap<String, Object>();
            
            if(prdName!=null){
                condition.put("prdName", prdName);
            }
            if(typeId!=null && typeId>0){
                condition.put("typeId", typeId);
            }
            if(lowPrice!=null){
                condition.put("lowPrice", lowPrice);
            }
            if(highPrice!=null){
                condition.put("highPrice", highPrice);
            }
            //将检索条件保存到session中
            req.getSession().setAttribute(Constants.SESSION_SEARCH_COND_KEY, condition);
             //获取商品所有类别
            List<ProductTypeInfo> typeList = this.productTypeService.getAllTypes();
            req.setAttribute("typeList", typeList);
            //获取总页数
            int pageCount = this.productService.getPageCount(condition);
            req.setAttribute("pageCount", pageCount);
            //查询到的商品信息
            List<ProductInfo> prdList = this.productService.search(condition, 1);
            req.setAttribute("prdList", prdList);
             
            req.setAttribute("current", 1 );
            req.getRequestDispatcher("/prd/prd_search.jsp").forward(req, resp);
            
        }
    }
}

3.service 服务代码

package com.xixi.demo.service;

import com.sun.javafx.collections.MappingChange.Map;
import com.xixi.demo.common.Constants;
import java.util.HashMap;
import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.xixi.demo.common.DBUtils;
import com.xixi.demo.dao.ProductMapper;
import com.xixi.demo.vo.ProductInfo;

public class ProductService {
    /**
     * 
     *获取所有产品 
     * 
     * @return
     */
    public List<ProductInfo> getAllProducts() {
        //获取sqlsession对象
        SqlSession session = DBUtils.getSqlSession();
        //获取ProductMapper实例
        ProductMapper prdMapper = session.getMapper(ProductMapper.class);
        List<ProductInfo> list = null;
        try {
            list = prdMapper.getAllProducts();
            session.commit();
        } catch (Exception e) {
            session.rollback();
            e.printStackTrace();
        }finally{
            session.close();
        }
        return list;
    }

    /**
     * 
     * 商品检索
     * 
     * @param condition
     * @param pageNum
     * @return
     */
    public List<ProductInfo> search(HashMap<String, Object> condition,  int pageNum) {
        SqlSession session = DBUtils.getSqlSession();
        ProductMapper prdMapper = session.getMapper(ProductMapper.class);
        List<ProductInfo> list = null;
        try {
            //使用mybatis后,dao层的方法只能接受一个参数,所以将pageNum封装成一个Map对象放入condition中
            condition.put("startRowNum", (pageNum-1)*Constants.PAGE_SIZE);
            condition.put("pageSize", Constants.PAGE_SIZE);
            list = prdMapper.search(condition);
            session.commit();
        } catch (Exception e) {
            session.rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }
        return list;
    }
    /**
     * 
     * 获取总页数
     * 
     * @param condition
     * @return
     */
    public int getPageCount(HashMap<String, Object> condition) {
        SqlSession session = DBUtils.getSqlSession();
        ProductMapper prdMapper = session.getMapper(ProductMapper.class);
        int recordCount = 0; 
        try {
            recordCount = prdMapper.getRecordCount(condition);
            session.commit();
        } catch (Exception e) {
            session.rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }
        return (recordCount + Constants.PAGE_SIZE -1) / Constants.PAGE_SIZE;
    }

}

4.使用Mybatis进行dao层设计。


ProductMapper.xml dao层配置文件,处理相关CRUD操作,通过数据库访问数据。
<?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.xixi.demo.dao.ProductMapper">
    <!-- type javaBean类型    id 对应resultMap的值 -->
    <resultMap type="ProductInfo" id="rm1">
        <id column="productId" property="prdId"/><!-- 设置主键映射 -->
        <result column="productName" property="prdName"/><!-- 设置其他参数 -->
        <result column="productTypeId" property="typeId"/>
        <result column="productDescription" property="desc"/>
        <result column="productPrice" property="price"/>
    </resultMap>
    <!-- 定义sql语句的片段  将重用的语句进行定义 -->
    <sql id="sql1">
        SELECT    productId,
                            productName,
                            productTypeId,
                            productDescription,
                            productPrice
        FROM products
    </sql>
    
    <select id="getAllProducts"  resultMap="rm1">
        <include refid="sql1"/>
    </select>
    <select id="getInfoById" parameterType="integer" resultMap="rm1">
        <include refid="sql1"/>
        where productId = #{prdId};<!-- 使用#{}作为参数的占用符,将参数传入其中 -->
    </select>
    
    <!--  不需要声明结果类型resultType,delete update insert操作默认返回的结果类型为int类型 -->
    <insert id="saveInfo" parameterType="ProductInfo" useGeneratedKeys="true" keyProperty="productId">
        insert into products(productName, productTypeId, productDescription,productPrice) 
        values( #{prdName},
                        #{typeId},
                        #{desc},
                        #{price })
    </insert>
    
    <select id="search" parameterType="map" resultMap="rm1" >
        <include refid="sql1"/>
       <where>
            <if test="prdName!=null">productName like concat('%', #{prdName}, '%')</if>
            <if test="typeId!=null and typeId>0">and productTypeId=#{typeId}</if>
            <if test="lowPrice!=null">and productPrice >= #{lowPrice}</if>
           <!--    <if test="highPrice!=null">and  #{highPrice} >= productPrice </if>-->
           <if test="highPrice!=null"><![CDATA[and  productPrice <= #{highPrice} ]]> </if>
       </where>
       order by productId asc limit #{startRowNum}, #{pageSize}
    </select>
    
    <select id="getRecordCount" parameterType="map" resultType="_int">
       select count(*)
       from products
       <where>
            <if test="prdName!=null">productName like concat('%', #{prdName}, '%')</if>
            <if test="typeId!=null and typeId>0">and productTypeId=#{typeId}</if>
            <if test="lowPrice!=null">and productPrice >= #{lowPrice}</if>
           <!--    <if test="highPrice!=null">and  #{highPrice} >= productPrice </if>-->
           <if test="highPrice!=null"><![CDATA[and  productPrice <= #{highPrice} ]]> </if>
       </where>       
    </select>
</mapper>

ProductMapper.java dao层接口,定义业务处理的方法,与Mybatis框架交互。
package com.xixi.demo.dao;

import java.util.HashMap;
import java.util.List;

import com.sun.javafx.collections.MappingChange.Map;
import com.xixi.demo.vo.ProductInfo;

public interface ProductMapper {
    //获取所有的产品
    List<ProductInfo> getAllProducts();
    //通过某一个产品编号查询产品信息
    ProductInfo getInfoById(Integer prdId);
    //录入新的商品
    int saveInfo(ProductInfo info);
    //检索商品
    List<ProductInfo> search(HashMap<String, Object> condition);
    //获取产品记录条数
    int getRecordCount(HashMap<String, Object> condition);
}

注:
Mybatis框架是用过程中,dao层定义的接口的名称必须与对应的xml文件同名。

5.Mybatis核心配置文件


(1)由于返回值类型过长,通过给javaBean对象起别名进行简化。
        <!-- 由于返回值类型过长,通过给javaBean对象起别名进行简化 -->
        <typeAliases>
            <typeAlias type="com.xixi.demo.vo.ProductInfo" alias="ProductInfo"/>
            <typeAlias type="com.xixi.demo.vo.UserInfo" alias="UserInfo"/>
            <typeAlias type="com.xixi.demo.vo.ProductTypeInfo" alias="ProductTypeInfo"/>
        </typeAliases>

(2)配置数据库环境,数据库连接,数据库驱动,数据库url,数据库名称,密码,数据库最大连接数,最大空闲数。
 <!-- 数据库环境 -->
            <environments default="demo">
                    <environment id="demo">
                            <transactionManager type="JDBC"></transactionManager>
                            <dataSource type="POOLED">
                                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                                    <property name="url" value="jdbc:mysql://localhost:3306/struts"/>
                                    <property name="username" value="struts2"/>
                                    <property name="password" value="struts2"/>
                                    <property name="poolMaximumActiveConnections" value="20"/>
                                    <property name="poolMaximumIdleConnections" value="15"/>
                            </dataSource>
                    </environment>
        </environments>
        

(3)映射XML文件资源路径
 <mapper resource="com/xixi/demo/dao/ProductMapper.xml"/>


configuration.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
  
<configuration>
        <!-- 由于返回值类型过长,通过给javaBean对象起别名进行简化 -->
        <typeAliases>
            <typeAlias type="com.xixi.demo.vo.ProductInfo" alias="ProductInfo"/>
            <typeAlias type="com.xixi.demo.vo.UserInfo" alias="UserInfo"/>
            <typeAlias type="com.xixi.demo.vo.ProductTypeInfo" alias="ProductTypeInfo"/>
        </typeAliases>
        <!-- 数据库环境 -->
            <environments default="demo">
                    <environment id="demo">
                            <transactionManager type="JDBC"></transactionManager>
                            <dataSource type="POOLED">
                                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                                    <property name="url" value="jdbc:mysql://localhost:3306/struts"/>
                                    <property name="username" value="struts2"/>
                                    <property name="password" value="struts2"/>
                                    <property name="poolMaximumActiveConnections" value="20"/>
                                    <property name="poolMaximumIdleConnections" value="15"/>
                            </dataSource>
                    </environment>
        </environments>
        
        <!--映射XML文件资源路径 -->     
        <mappers>
            <mapper resource="com/xixi/demo/dao/UserMapper.xml"/>
            <mapper resource="com/xixi/demo/dao/ProductMapper.xml"/>
            <mapper resource="com/xixi/demo/dao/ProductTypeMapper.xml"/>
        </mappers>
</configuration>

相关文章

  • mybatis动态条件查询及数据库数据的分页查询实现

    一、需求分析 1.对于前端页面为多个条件进行检索的情况,查询条件个数不确定的情况,可使用元素。如下:...

  • Mybatis分页的自我理解

    mybatis分页思想: 当查询的数据量很大时需要分页显示,然而不同的数据库分页查询也不同;mybatis采取的策...

  • Java面试题:Mybatis 是如何进行分页的(分页插件附源码

    1.Mybatis分页介绍 我们在项目中经常会查询数据列表,数据库不会显示所有的数据,而是分页显示,Mybatis...

  • Python操作三大数据库(1)-MySQL

    本章是直接操作MySQL数据库的实现方式 连接MySQL数据库 查询单条数据 查询多条数据 通过分页方式查询 插入...

  • 像查询DB一样查询redis

    设计目的:希望查询redis缓存像查询数据库一样,支持多条件组合查询、模糊查询、区间查询、多字段排序查询、分页查询...

  • spring集成mybatis使mybatis一级缓存失效

    使用mybatis查询数据库: spring集成mybatis查询数据库: 总结:spring集成mybatis进...

  • JAVA Web学习(16)___10.4 JDBC在Jave

    10.4 JDBC在Jave Web中的应用 分页查询 通过MySQL数据库提供的分页机制,实现商品信息的分页查询...

  • MySQL03

    DQL查询语句 分页查询 分组函数 分组查询 子查询 多表连接查询 1、分页查询 当数据库中数据过多时,不能一次全...

  • mybatis

    介绍 mybatis 加载配置文件 增删改查/分页查询 别名配置 定义结果集 动态SQL(增删改查/分页查询) 关...

  • SQL基础(一)

    问 介绍下数据库分页原理: 使用LIMIT子句实现分页查询 在所有的查询结果中,返回前5行记录。SELECT ...

网友评论

      本文标题:mybatis动态条件查询及数据库数据的分页查询实现

      本文链接:https://www.haomeiwen.com/subject/egcjvctx.html