一.概述
对于java中,前端对于多条件的查询,往往参数过多,如果后端在接收参数的时候不进行封装,会使得代码重复率高,代码累赘,进行一定的封装和抽取,会大大提高代码的简洁和可维护性.
二.高级查询的封装示例
1.数据库建表
DROP TABLE IF EXISTS `product`;
CREATE TABLE `product` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`productName` varchar(50) DEFAULT NULL,
`dir_id` bigint(11) DEFAULT NULL,
`salePrice` decimal(10,2) DEFAULT NULL,
`supplier` varchar(50) DEFAULT NULL,
`brand` varchar(50) DEFAULT NULL,
`cutoff` double(2,2) DEFAULT NULL,
`costPrice` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `dir_id` (`dir_id`),
CONSTRAINT `product_ibfk_1` FOREIGN KEY (`dir_id`) REFERENCES `productdir` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `productdir`;
CREATE TABLE `productdir` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`dirName` varchar(30) DEFAULT NULL,
`parent_id` bigint(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
2.javaBean
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {
private Long id; // 商品编号
private String productName; // 商品名称
private Long dir_id; //商品分类
private BigDecimal salePrice; // 售价
private String supplier; // 供应商
private String brand; // 商标
private Double cutoff; // 折价
private BigDecimal costPrice; // 成本价
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProductDir {
private Long id; //商品分类编号
private String dirName; //分类名称
private Long parent_id; // 分类的父分类
}
3.封装查询对象
//公用的查询对象
@Data
public class QueryObject {
// 存放sql的条件
private List<String> conditions = new ArrayList<>();
// 存放sql中的参数的值
private List<Object> params = new ArrayList<>();
// 拼接sql语句
public String getQuery() {
StringBuilder sb = new StringBuilder();
customizedQuery();
// 拼接sql
for (int i = 0; i < conditions.size(); i++) {
if (i == 0) {
sb.append(" WHERE ");
} else {
sb.append(" AND ");
}
sb.append(conditions.get(i));
}
return sb.toString();
}
// 专门暴露给子类实现
protected void customizedQuery() {
}
//将子类中的条件和参数传递给当前类中的对应的集合
protected void addQuery(String condition, Object... params) {
//当有多个条件的时候,应该在条件前后加上()
if(params.length>1){
this.conditions.add("("+condition+")");
}else{
this.conditions.add(condition);
}
this.params.addAll(Arrays.asList(params));
}
}
@Data
public class ProductQueryObject extends QueryObject {
private String productName;
private BigDecimal minSalePrice;
private BigDecimal maxSalePrice;
// 商品分类的编号
private Long dir_id;
// 关键字 商品的名称/品牌/供应商
private String keyword;
// 获取查询的条件和参数,自定义的查询方法
protected void customizedQuery() {
if (StringUtil.hasLength(productName)) {
super.addQuery(" productName LIKE ?", "%" + productName + "%");
}
if (minSalePrice != null) {
super.addQuery(" salePrice >=?", minSalePrice);
}
if (maxSalePrice != null) {
super.addQuery(" salePrice <=?", maxSalePrice);
}
if (dir_id != null && dir_id != -1L) {
super.addQuery(" dir_id =?", dir_id);
}
if (StringUtil.hasLength(keyword)) {
super.addQuery(
" productName LIKE ? OR brand LIKE ? OR supplier LIKE ?",
"%" + keyword + "%", "%" + keyword + "%", "%" + keyword
+ "%");
}
}
}
@Data
public class ProductDirQueryObject extends QueryObject {
private String name;
// 获取查询的条件和参数,自定义的查询方法
protected void customizedQuery() {
if (StringUtil.hasLength(name)) {
super.addQuery(" dirName LIKE ?", "%" + name + "%");
}
}
}
4.Serverlet
@WebServlet("/product")
public class ProductServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// 商品的dao对象
private IProductDAO productDao;
// 商品分类dao对象
private IProductDirDAO productDirDao;
@Override
public void init() throws ServletException {
productDao = new ProductDAOImpl();
productDirDao = new ProductDirDAOImpl();
}
protected void list1(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
ProductQueryObject qo = getProductQueryObject(req);
List<Product> list = productDao.query(qo);
List<ProductDir> dirList = productDirDao.list();
req.setAttribute("list", list);
req.setAttribute("dirList", dirList);
req.setAttribute("qo", qo);
req.getRequestDispatcher("/WEB-INF/views/product/list.jsp").forward(
req, resp);
}
// 封装查询对象
private ProductQueryObject getProductQueryObject(HttpServletRequest req) {
// 获取请求参数
String productName = req.getParameter("productName");
String minSalePrice = req.getParameter("minSalePrice");
String maxSalePrice = req.getParameter("maxSalePrice");
String dir_id = req.getParameter("dir_id");
String keyword = req.getParameter("keyword");
String currentPage = req.getParameter("currentPage");
String pageSize = req.getParameter("pageSize");
// 默认的页面
Integer iCurrentPage = 1;
// 默认的页面大小
Integer iPageSize = 3;
if (StringUtil.hasLength(currentPage)) {
iCurrentPage = Integer.valueOf(currentPage);
}
if (StringUtil.hasLength(pageSize)) {
iPageSize = Integer.valueOf(pageSize);
}
// 封装查询对象
ProductQueryObject qo = new ProductQueryObject();
qo.setProductName(productName);
if (StringUtil.hasLength(minSalePrice)) {
qo.setMinSalePrice(new BigDecimal(minSalePrice));
}
if (StringUtil.hasLength(maxSalePrice)) {
qo.setMaxSalePrice(new BigDecimal(maxSalePrice));
}
if (StringUtil.hasLength(dir_id)) {
qo.setDir_id(Long.valueOf(dir_id));
}
if (StringUtil.hasLength(keyword)) {
qo.setKeyword(keyword);
}
return qo;
}
}
5.前端页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>货品显示列表</title>
<!-- 新 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet"
href="/bootstrap/bootstrap.min.css">
<!-- 可选的Bootstrap主题文件(一般不用引入) -->
<link rel="stylesheet"
href="/bootstrap/bootstrap-theme.min.css">
<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="/bootstrap/jquery.min.js"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="/bootstrap/bootstrap.min.js"></script>
<script type="text/javascript">
function go(currentPage) {
//将当前页的数据设置给currentPage隐藏域
document.getElementById("currentPage").value = currentPage;
//提交表单
document.forms[0].submit();
}
</script>
</head>
<body>
<a href="${pageContext.request.contextPath}/product?cmd=edit">添加货品</a>
<!-- 高级查询 开始-->
<form action="/product" method="post">
<input name="currentPage" id="currentPage" value="" type="hidden" />
商品的名称:<input name="productName" value="${qo.productName}" /> 商品零售价:<input
type="number" name="minSalePrice" value="${qo.minSalePrice}" /> -<input
type="number" name="maxSalePrice" value="${qo.maxSalePrice}" />
商品分类:<select name="dir_id">
<option value='-1'>..请选择...</option>
<c:forEach items="${dirList}" var="dir">
<option value='${dir.id}'
${qo.dir_id==dir.id?'selected=selected':''}>${dir.dirName}</option>
</c:forEach>
</select> 关键字:<input name="keyword" placeholder="名称/品牌/供应商"
value="${qo.keyword}" /> <input type="submit" value="查询" /> <input
type="reset" value="重置" />
</form>
<!-- 高级查询 结束-->
<form action="${pageContext.request.contextPath}/product" method="post" id="form2">
<table border="1" cellpadding="0" cellspacing="0" width="90%">
<tr>
<th>货品编号</th>
<th>货品名称</th>
<th>货品品牌</th>
<th>货品分类</th>
<th>供 应 商</th>
<th>零 售 价</th>
<th>成 本 价</th>
<th>折  扣</th>
<th>操  作</th>
</tr>
<c:if test="${empty page.listData}">
<tr>
<td colspan="9" style="text-align: center; color: red;">亲,没有查询到您需要的数据~~~</td>
</tr>
</c:if>
<c:forEach items="${page.listData}" var="pro" varStatus="vs">
<tr>
<td>${pro.id}</td>
<td>${pro.productName}</td>
<td>${pro.brand}</td>
<td>${pro.dir_id}</td>
<td>${pro.supplier}</td>
<td>${pro.salePrice}</td>
<td>${pro.costPrice}</td>
<td>${pro.cutoff}</td>
<td><a href="/product?cmd=edit&id=${pro.id}">编辑</a> | <a
href="${pageContext.request.contextPath}/product?cmd=delete&id=${pro.id}">删除</a>
</td>
</tr>
</c:forEach>
</table>
</form>
</body>
</html>