JDBC的多条件动态查询

首先我们先分析一下多条件综合查询的实现方式有哪些?

1、直接将参数值拼接到SQL语句中,然后进行Select,但是说这种方式存在安全性问题,比如说SQL的注入,尽管我们可以通过正则等手段来过滤掉这些特殊字符,但是这样看上去不是很爽。

2、先使用占位符“?”来拼接SQL,然后再通过条件判断去填充PreparedStatement,但是这种方式显然很麻烦,因为我们在拼SQL的时候需要判断一次,在填充pst的时候还需要再进行判断,所以不是好的解决方案。

3、存储过程,这个因为本人对存储过程认识不是很深,所以这里不加描述;

其实方法很多,只是找一个相对好一点的,工作的这段时间做.NET项目时使用里面的SqlHelper感觉很犀利,记得以前学习的时候老师也给我们做了一个类似的,所以想写一个工具类。

Parameter.java:

 1 package com.iflytek.page;
 2 
 3 /**
 4  * 查询参数工具类,用于表示条件参数对象
 5  * 
 6  * @author xudongwang 2012-1-19
 7  * 
 8  *         Email:xdwangiflytek@gmail.com
 9  */
10 public class Parameter {
11     /**
12      * 数据库字段名
13      */
14     private String field;
15     /**
16      * 参数值 Object
17      */
18     private Object value;
19     /**
20      * 数据库操作符 =、>=、<、like...
21      */
22     private String operator;
23 
24     /**
25      * 构造方法
26      * 
27      * @param field
28      *            数据库字段名
29      * @param operator
30      *            数据库操作符 =、>=、<、like...
31      * @param value
32      *            参数值 Object
33      */
34     public Parameter(String field, String operator, Object value) {
35         super();
36         this.field = field;
37         this.value = value;
38         this.operator = operator;
39     }
40 
41     public String getField() {
42         return field;
43     }
44 
45     public Object getValue() {
46         return value;
47     }
48 
49     public String getOperator() {
50         return operator;
51     }
52 }

DynamicQuery.java:

 1 package com.iflytek.page;
 2 
 3 import java.sql.PreparedStatement;
 4 import java.sql.SQLException;
 5 import java.util.ArrayList;
 6 
 7 /**
 8  * 动态查询工具类,用于拼接SQL、填充PreparedStatement
 9  * 
10  * @author xudongwang 2012-1-19
11  * 
12  *         Email:xdwangiflytek@gmail.com
13  */
14 public class DynamicQuery {
15 
16     private String templet = " AND %s %s ?";
17     private String baseSql;
18     private ArrayList<Parameter> parameters = new ArrayList<Parameter>();
19 
20     public DynamicQuery() {
21 
22     }
23 
24     /**
25      * baseSql需要带有where条件
26      * 
27      * @param baseSql
28      */
29     public void setBaseSql(String baseSql) {
30         this.baseSql = baseSql;
31     }
32 
33     public void addParameter(Parameter parameter) {
34         parameters.add(parameter);
35     }
36 
37     public String generateSql() {
38         StringBuffer sb = new StringBuffer(baseSql);
39         for (Parameter parameter : parameters) {
40             sb.append(String.format(templet, parameter.getField(),
41                     parameter.getOperator()));
42         }
43         return sb.toString();
44     }
45 
46     public void fillPreparedStatement(PreparedStatement pst)
47             throws SQLException {
48         int count = 1;
49         for (Parameter p : parameters) {
50             // 这里使用SetObjcet的缺点是失去了类型的验证功能,如果大家不嫌麻烦,可以判断,根据类型,set不同的类型
51             pst.setObject(count, p.getValue());
52             count++;
53         }
54     }
55 
56 }

SelectServlet.java:

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

StduentDao.java:

 1 public List<Student> selectByQuery(DynamicQuery query) {  
 2         
 3         List<Student> students = new ArrayList<Student>();  
 4   
 5         try {  
 6             String sql = "SELECT id,name,email FROM tbl_stduent";  
 7   
 8             query.setBaseSql(sql);  
 9             //如果想排序,自行在sql后添加  
10             sql = query.generateSql();
11             Connection conn = null;  
12             try {  
13                 conn = DbUtil.getConnection();  
14                 PreparedStatement pst= conn.prepareStatement(sql);  
15               //填充pst  
16                 query.fillPreparedStatement(pst);
17                 ResultSet rs = pst.executeQuery();  
18                 while (rs.next()) {  
19                     Student student = new Student();  
20                     ……  
21                     students.add(student);  
22                 }  
23                 rs.close();  
24                 pst.close();  
25             } finally {  
26                 if (conn != null) {  
27                     conn.close();  
28                 }  
29             }  
30         } catch (Exception e) {  
31             e.printStackTrace();  
32         }  
33         return students;  
34     }

下面来总结一下上面的整个流程:

1、 首先我们在Servlet、Action等控制器里将需要查询的表单参数值添加到查询条件列表中;

2、 在数据访问层DAO中设置基本的SQL;

3、 下面我们来迭代查询条件列表,使用占位符拼接SQL;

4、 在DAO中拿SQL创建PreparedStatement;

5、 迭代查询条件列表,为pst填充值;

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

posted @ 2012-12-13 22:32  zdp072  阅读(892)  评论(0编辑  收藏  举报