在Web开发中,多种条件的综合查询非常常见,应对这种业务需求我们通常使用下面几种方法来实现:
PS:
i.(Hibernate的条件查询Criteria Queries当然是非常方便的,本文仅探讨JDBC方式的使用)
ii.(欢迎高手、大拿们拍砖,请勿人身攻击)
1.直接将参数值拼接到SQL语句中,然后进行查询。
这种方式的安全性应当说是比较差的,一不小心就被SQL注入了。虽然可以先过滤参数值中的特殊字符,但总感觉不是很优雅。
2.先使用占位符'?'来拼接SQL,然后再通过条件判断去填充PreparedStatement。
用过这种方式的TX,都知道这种方式的复杂性。先要在拼SQL时判断一次,然后还要在填充pst时再判断一次,麻烦。
3.存储过程
本人一直不爽存储过程,以前有一个项目从MySQL迁移到MSSQL,后来又换成ORACLE,最后产品的不同版本运行在不同数据库上,当时差点要了亲命了。
其实讲这么多无非就是想要一种相对优雅简单的查询方式,前一段看到.NET中的SQLHelper受到一些启发,然后就写了这么一个类似的组件(其实我Google了半个小时都没有找到符合要求的)。
基本思想:
1.在控制器中(Servlet/Action etc...)中将查询表单中的参数值添加到查询条件列表中
2.在DAO(你明白的)中设置基本SQL
3.迭代查询条件列表,使用占位符拼接SQL
4.在DAO中拿SQL创建PreparedStatement
5.迭代查询条件列表,为pst填充值
6.接下来,没有特殊的地方了,就是正常的executeQuery,while(rs.next()){...}
将第1/2/3/5步骤的功能提取出来做成一个工具类,然后其它地方就可以随意使用了,嘿嘿
好了,不啰嗦了直接上代码吧
Parameter.java
- /**
- * 查询参数类,用于表示条件参数对象
- * @author Lixor(at)live.cn
- *
- */
- public class Parameter{
- private String field;
- private Object value;
- private String operator;
- /**
- *
- * @param field 数据库字段名
- * @param operator 数据库操作符 =、>=、<、like etc...
- * @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;
- }
- }
/**
* 查询参数类,用于表示条件参数对象
* @author Lixor(at)live.cn
*
*/
public class Parameter{
private String field;
private Object value;
private String operator;
/**
*
* @param field 数据库字段名
* @param operator 数据库操作符 =、>=、<、like etc...
* @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
- /**
- * 动态查询工具类,用于拼接SQL、填充pst
- * @author Lixor(at)live.cn
- *
- */
- public class DynamicQuery {
- private static Logger logger=Logger.getLogger(DynamicQuery.class);
- 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 buffer = new StringBuffer(baseSql);
- for (Parameter p : parameters) {
- buffer.append(String.format(templet, p.getField(), p.getOperator()));
- }
- logger.debug(buffer);
- return buffer.toString();
- }
- public void fillPreparedStatement(PreparedStatement pst) throws SQLException {
- int count = 1;
- for (Parameter p : parameters) {
- pst.setObject(count, p.getValue());
- count++;
- }
- }
- }
/**
* 动态查询工具类,用于拼接SQL、填充pst
* @author Lixor(at)live.cn
*
*/
public class DynamicQuery {
private static Logger logger=Logger.getLogger(DynamicQuery.class);
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 buffer = new StringBuffer(baseSql);
for (Parameter p : parameters) {
buffer.append(String.format(templet, p.getField(), p.getOperator()));
}
logger.debug(buffer);
return buffer.toString();
}
public void fillPreparedStatement(PreparedStatement pst) throws SQLException {
int count = 1;
for (Parameter p : parameters) {
pst.setObject(count, p.getValue());
count++;
}
}
}
示例:查询产品信息
QueryServlet.java
- DynamicQuery query=new DynamicQuery();
- query.addParameter(new Parameter("p.name" ,"like","电视"));
- query.addParameter(new Parameter("p.type_id","=" ,1));
- query.addParameter(new Parameter("p.productDate" ,">=",java.sql.Date.valueOf("2010-09-04")));
- query.addParameter(new Parameter("p.price" ,">=",1000.0f));
- ProductDao dao=new ProductDao();
- List<Product> productList=dao.query(query);
- request.setAttribute("productList",productList);
DynamicQuery query=new DynamicQuery();
query.addParameter(new Parameter("p.name" ,"like","电视"));
query.addParameter(new Parameter("p.type_id","=" ,1));
query.addParameter(new Parameter("p.productDate" ,">=",java.sql.Date.valueOf("2010-09-04")));
query.addParameter(new Parameter("p.price" ,">=",1000.0f));
ProductDao dao=new ProductDao();
List<Product> productList=dao.query(query);
request.setAttribute("productList",productList);
ProductDao.java
- public List<Product> query(DynamicQuery query) {
- List<Product> productList = new ArrayList<Product>();
- try {
- String sql = "SELECT p.id,p.name,p.price,p.productDate,p.image,p.type_id,t.name,p.description FROM tbl_product p,tbl_type t WHERE p.type_id=t.id";
- query.setBaseSql(sql);
- sql = query.generateSql();//如果想排序,自行在sql后添加
- Connection conn = null;
- try {
- conn = DbUtil.getConnection();
- PreparedStatement pst= conn.prepareStatement(sql);
- query.fillPreparedStatement(pst);//填充pst
- ResultSet rs = pst.executeQuery();
- while (rs.next()) {
- Product product = new Product();
- ……
- productList.add(product);
- }
- rs.close();
- pst.close();
- } finally {
- if (conn != null) {
- conn.close();
- }
- }
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return productList;
- }

浙公网安备 33010602011771号