转载:基于JDBC的多条件动态查询实现

博客介绍了在Web开发中如何使用JDBC实现多条件动态查询,包括直接拼接SQL的不安全性,使用PreparedStatement的复杂性,以及存储过程的不便。作者受.NET SQLHelper启发,提出了一种更优雅的解决方案,通过将查询条件列表与占位符结合,简化了SQL的构造和参数填充。文章提供了Parameter和DynamicQuery两个关键类的代码示例,以及一个查询产品的应用示例。

基于JDBC的多条件动态查询实现

JDBCSQLDAOOracleHibernate 

 

转载自:https://www.iteye.com/blog/lixor-765217  感谢  id:yvfish   大神

 

在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
Java代码 

  1. /** 
     * 查询参数类,用于表示条件参数对象 
     * @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代码 

 

  1. /** 
     * 动态查询工具类,用于拼接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;  
    }  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值