您的位置:首页 > 其它

JDBC的多条件动态查询

2012-04-10 09:29 204 查看
在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;

}

}

DynamicQuery.java

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++;

}

}

}

示例:查询产品信息

QueryServlet.java

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);

ProductDao.java

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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: