JDBC的多條件動態查詢

fmms 12年前發布 | 67K 次閱讀 JDBC Java開發

前面我已經提到了現在的項目無非就是列表里的分頁加多條件查詢,在http://xdwangiflytek.iteye.com/blog/1358080里我已經簡單的歸納了一下分頁的實現手段和JDBC里的分頁,這里我們在來說說JDBC里的多條件動態查詢,為什么說多條件,因為在項目列表中,不可能只有只有一個字段,所以說條件也不可能只有一個,所以這里我們還是說一下多條件下的查詢,多條件ok了那么單個條件不更ok了么(Hibernate里有Criteria Queries哦)。

首先我們和分頁一樣先分析一下多條件綜合查詢的實現方式有哪些?

1、直接將參數值拼接到SQL語句中,然后進行Select,但是說這種方式存在安全性問題,比如說SQL的注入,盡管我們可以通過正則等手段來過濾掉這些特殊字符,但是這樣看上去不是很爽。

2、先使用占位符“?”來拼接SQL,然后再通過條件判斷去填充PreparedStatement,但是這種方式顯然很麻煩,因為我們在拼SQL的時候需要判斷一次,在填充pst的時候還需要再進行判斷,所以不是好的解決方案。

3、存儲過程,這個因為本人對存儲過程認識不是很深,所以這里不加描述;

其實方法很多,只是找一個相對好一點的,工作的這段時間做.NET項目時使用里面的SqlHelper感覺很犀利,記得以前學習的時候老師也給我們做了一個類似的,所以想寫一個工具類。

 

Parameter.java:

package com.iflytek.page;

/**
 * 查詢參數工具類,用于表示條件參數對象
 * 
 * @author xudongwang 2012-1-19
 * 
 *         Email:xdwangiflytek@gmail.com
 */
public class Parameter {
    /**
     * 數據庫字段名
     */
    private String field;
    /**
     * 參數值 Object
     */
    private Object value;
    /**
     * 數據庫操作符 =、>=、<、like...
     */
    private String operator;

    /**
     * 構造方法
     * 
     * @param field
     *            數據庫字段名
     * @param operator
     *            數據庫操作符 =、>=、<、like...
     * @param value
     *            參數值 Object
     */
    public Parameter(String field, String operator, Object value) {
        super();
        this.field = field;
        this.value = value;
        this.operator = operator;
    }

    public String getField() {
        return field;
    }

    public Object getValue() {
        return value;
    }

    public String getOperator() {
        return operator;
    }
}

 

 DynamicQuery.java:

package com.iflytek.page;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;

/**
 * 動態查詢工具類,用于拼接SQL、填充PreparedStatement
 * 
 * @author xudongwang 2012-1-19
 * 
 *         Email:xdwangiflytek@gmail.com
 */
public class DynamicQuery {

    private String templet = " AND %s %s ?";
    private String baseSql;
    private ArrayList<Parameter> parameters = new ArrayList<Parameter>();

    public DynamicQuery() {

    }

    /**
     * baseSql需要帶有where條件
     * 
     * @param baseSql
     */
    public void setBaseSql(String baseSql) {
        this.baseSql = baseSql;
    }

    public void addParameter(Parameter parameter) {
        parameters.add(parameter);
    }

    public String generateSql() {
        StringBuffer sb = new StringBuffer(baseSql);
        for (Parameter parameter : parameters) {
            sb.append(String.format(templet, parameter.getField(),
                    parameter.getOperator()));
        }
        return sb.toString();
    }

    public void fillPreparedStatement(PreparedStatement pst)
            throws SQLException {
        int count = 1;
        for (Parameter p : parameters) {
            // 這里使用SetObjcet的缺點是失去了類型的驗證功能,如果大家不嫌麻煩,可以判斷,根據類型,set不同的類型
            pst.setObject(count, p.getValue());
            count++;
        }
    }

}

 

 SelectServlet.java:

   DynamicQuery query = new DynamicQuery();
        query.addParameter(new Parameter("name", "like", "xudongwang"));
        query.addParameter(new Parameter("email", "=", "xdwangiflytek@gmail.com"));
        StudentDao studentDao = new StudentDao();
        List<Stduent> students = studentDao.selectByQuery(query);
        request.setAttribute("students", students);

 

StduentDao.java:

public List<Student> selectByQuery(DynamicQuery query) {  

        List<Student> students = new ArrayList<Student>();  

        try {  
            String sql = "SELECT id,name,email FROM tbl_stduent";  

            query.setBaseSql(sql);  
            //如果想排序,自行在sql后添加  
            sql = query.generateSql();
            Connection conn = null;  
            try {  
                conn = DbUtil.getConnection();  
                PreparedStatement pst= conn.prepareStatement(sql);  
              //填充pst  
                query.fillPreparedStatement(pst);
                ResultSet rs = pst.executeQuery();  
                while (rs.next()) {  
                    Student student = new Student();  
                    ……  
                    students.add(student);  
                }  
                rs.close();  
                pst.close();  
            } finally {  
                if (conn != null) {  
                    conn.close();  
                }  
            }  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return students;  
    }
 

 

下面來總結一下上面的整個流程:

 1、 首先我們在ServletAction等控制器里將需要查詢的表單參數值添加到查詢條件列表中;

 2、 在數據訪問層DAO中設置基本的SQL

 3、 下面我們來迭代查詢條件列表,使用占位符拼接SQL

 4、 DAO中拿SQL創建PreparedStatement

 5、 迭代查詢條件列表,為pst填充值;

 6、 接下來,沒有特殊(是否添加排序)的地方了,就是正常的executeQuerywhile(rs.next()){...}

 本文由用戶 fmms 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!