Java中JDBC實現(xiàn)動態(tài)查詢的實例詳解
一 概述
1.什么是動態(tài)查詢?
從多個查詢條件中隨機選擇若干個組合成一個DQL語句進行查詢,這一過程叫做動態(tài)查詢。
2.動態(tài)查詢的難點
可供選擇的查詢條件多,組合情況多,難以一一列舉。
3.最終查詢語句的構成
一旦用戶向查詢條件中輸入數(shù)據(jù),該查詢條件就成為最終條件的一部分。
二 基本原理
1.SQL基本框架
無論查詢條件如何,查詢字段與數(shù)據(jù)庫是固定不變的,這些固定不變的內容構成SQL語句的基本框架,如
select column... from table。
2.StringBuilder形成DQL
獲取表單輸入,如果請求參數(shù)非空,根據(jù)該請求參數(shù)生成查詢條件,如“name=?”,“age>?”,將查詢條件追加到基本框架中。利用StringBuilder來追加查詢條件,這時出現(xiàn)一個問題,怎么判斷生成的查詢條件中是否需要添加“and”?
如果該查詢條件是第一個查詢條件,不需要添加"and",否則需要添加“and”。問題變得復雜起來,每一次生成查詢條件時都需要判斷前面是否存在查詢條件。
我們可以考慮在SQL基本框架中添加一個查詢條件,該查詢條件的存在不影響查詢結果,只充當占位角色,避免動態(tài)添加查詢條件時判斷是否需要添加“and”。根據(jù)這些要求,這一查詢條件必須恒為真,這里我們取“1=1”,SQL基本框架就變成了
select column...from table where 1=1
每一個動態(tài)查詢條件前段都添加“and”。
3.List集合為占位符賦值
有了DQL語句,接著需要考慮怎么為占位符賦值。可以在生成查詢條件的同時,將占位符對應的參數(shù)收集起來,存入一個有序集合中,這里選擇List集合,這樣占位符就與List集合中的元素形成了順序上的對應關系,第n個占位符對應第n個元素,遍歷集合就可以為占位符賦值了。
為占位符賦值時,不僅僅需要將數(shù)據(jù)傳遞給占位符,還需要選擇與字段一致的數(shù)據(jù)類型,List集合僅僅存儲數(shù)據(jù)已經不能夠滿足要求了,還需要添加字段信息,以區(qū)分不同的字段,選擇不同的數(shù)據(jù)類型。這里集合中的元素采用“column+data”的形式。
三 Demo
1.數(shù)據(jù)庫
2.頁面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
span {
display: inline-block;
width: 75px;
margin-bottom: 15px;
}
</style>
<title>動態(tài)查詢</title>
</head>
<body>
<form action="http://localhost:8080/JavaSETest/dynamicQueryServlet">
<div>
<span>姓名:</span><input type="text" name="name">
</div>
<div>
<span>性別:</span><input type="text" name="sex">
</div>
<div>
<span>年齡:</span><input type="text" name="age">
</div>
<div>
<span>部門編號:</span><input type="text" name="depNo">
</div>
<div>
<input type="submit"value="查詢"> <input type="reset"value="重置">
</div>
</form>
</body>
</html>
3.服務器端(Servlet)
package com.javase.jdbc;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
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;
@WebServlet("/dynamicQueryServlet")
public class DynamicQueryServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
// 獲取請求參數(shù)
String name = request.getParameter("name");
String sex = request.getParameter("sex");
String age = request.getParameter("age");
String depNo = request.getParameter("depNo");
// 關鍵是"where 1=1",不需要再判斷追加的查詢條件前是否需要添加and,統(tǒng)一在前面添加and
String baseSQL = "select name,sex,age,depNo from tb_employee where 1=1";
StringBuilder builder = new StringBuilder();// 用于拼接SQL語句
// 用于在占位符與參數(shù)值之間建立映射,占位符與參數(shù)值在各自序列中的排序一相同,例如name的占位符在SQL語句中排第一,name的參數(shù)值在
// 集合中排第一。
List<String> params = new ArrayList<String>();
builder.append(baseSQL);
if (isNotEmpty(name)) {
builder.append(" and name=? ");
params.add("name," + name);// 集合中不能僅僅存儲具體的數(shù)據(jù),還要存儲字段名,以便后續(xù)根據(jù)字段名選擇數(shù)據(jù)類型
}
if (isNotEmpty(sex)) {
builder.append(" and sex=? ");
params.add("sex," + sex);
}
if (isNotEmpty(age)) {
builder.append(" and age=? ");
params.add("age," + age);
}
if (isNotEmpty(depNo)) {
builder.append(" and depNo=?");
params.add("depNo," + depNo);
}
Connection conn = null;
PreparedStatement ps = null;
ResultSet res = null;
StringBuilder resStr = new StringBuilder();
try {
conn = getConnection();
ps = conn.prepareStatement(builder.toString());
for (int i = 0; i < params.size(); i++) {
String str = params.get(i);
String[] arr = str.split(",");//arr[0]儲存字段信息,用于區(qū)分字段;arr[1]存儲數(shù)據(jù),用于為占位符賦值
// 因為為占位符賦值時,需要根據(jù)字段類型選擇數(shù)據(jù)類型,所以在此判斷類型
if (arr[0].equals("age")) {
int a = Integer.parseInt(arr[1]);
ps.setInt(i + 1, a);
} else {
ps.setString(i + 1, arr[1]);
}
}
res = ps.executeQuery();
while (res.next()) {
String targetName = res.getString("name");
String targetSex = res.getString("sex");
int targetAge = res.getInt("age");
String targetDepNo = res.getString("depNo");
String temp = "name=" + targetName + "--" + "sex=" + targetSex + "--" + "age=" + targetAge + "--"
+ "depNo=" + targetDepNo;
resStr.append(temp + "<br>");
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
if (res != null)
try {
res.close();
} catch (SQLException e) {
e.printStackTrace();
}
if (ps != null)
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
if (conn != null)
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
PrintWriter out = response.getWriter();
int length = resStr.length();
if (length == 0)
out.write("查詢?yōu)榭?);
else
out.write(builder.toString() + "<br>" + resStr.toString());
}
/**
* 判斷請求參數(shù)是否存在,是否有數(shù)據(jù)輸入
*
* @param str
* @return
*/
private boolean isNotEmpty(String str) {
if (str == null | str.equals("")) {
return false;
}
return true;
}
public static Connection getConnection() throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
return DriverManager.getConnection("jdbc:mysql://localhost:3366/test01", "root", "123");
}
}
以上所述是小編給大家介紹的Java中JDBC實現(xiàn)動態(tài)查詢的實例詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網站的支持!
相關文章
JAVA實現(xiàn)基于Tcp協(xié)議的簡單Socket通信實例
本篇文章主要介紹了JAVA實現(xiàn)基于Tcp協(xié)議的簡單Socket通信實例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01

