`

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()){...}

Ok88.

 

 

1
1
分享到:
评论
2 楼 drinkjava2 2016-11-23  
太复杂了而且不通用,利用ThreadLocal可完美解决这一问题,参见 http://drinkjava2.iteye.com/blog/2340020
以下为代码示例,参数利用q()方法暂存到Threadlocal中去,在SQL执行中取出来并装入preparedStatement:
public int conditionQuery(int condition, Object parameter) {//动态拼接SQL查询   
            User u = new User();   
            String sql = "Select count(*) from " + u.Table() + " where ";   
            if (condition == 1 || condition == 3)   
                sql = sql + u.UserName() + "=" + q(parameter) + " and " + u.Address() + "=" + q("Address1");   
       
            if (condition == 2)   
                sql = sql + u.UserName() + "=" + q(parameter);   
       
            if (condition == 3)   
                sql = sql + " or " + u.Age() + "=" + q(parameter);   
       
            return Dao.dao.queryForInteger(sql);   
        }   
       
        @Test   
        public void doJdbcConditionQuery() {   
            Assert.assertEquals(1, conditionQuery(1, "User1"));   
            Assert.assertEquals(0, conditionQuery(2, "User does not exist"));   
            Assert.assertEquals(1, conditionQuery(3, 10));   
            Assert.assertEquals(0, conditionQuery(3, 20));   
        }   
1 楼 jianxia801 2012-07-10  
哥们你的文章不错,值得一读!

相关推荐

    Java中JDBC实现动态查询的实例详解

    动态查询的难点在于可供选择的查询条件多,组合情况多,难以一一列举。 基本原理 1. SQL 基本框架:无论查询条件如何,查询字段与数据库是固定不变的,这些固定不变的内容构成 SQL 语句的基本框架,如 `select ...

    jdbc实现动态查询与分页查询的结合

    本文将深入探讨如何使用JDBC实现动态查询和分页查询的结合,这对于开发人员来说是一项基础但至关重要的技能。 首先,我们要了解JDBC的基础知识。JDBC是一个Java API,它提供了一系列的接口和类,使得Java程序员能够...

    jdbc+serlvet分页查询代码

    总结,"jdbc+serlvet分页查询代码"是Java Web开发中一个常见的应用场景,它展示了如何利用JDBC进行数据库操作,以及Servlet如何处理HTTP请求并返回动态生成的页面,同时包含了实现简单分页查询的策略。通过这个示例...

    JAVA,多条件,模糊查询,多个条件同时查询显示结果

    如果查询条件很多,可以考虑使用存储过程或者动态SQL来构建更复杂的查询逻辑。 综上所述,Java中的多条件模糊查询涉及数据库连接、SQL语句编写、预编译语句、结果集处理等多个环节,通过合理的设计和优化,可以有效...

    java配合MyBatis 多条件查询及动态SQL

    MyBatis 多条件查询及动态SQL 粉丝可见 ybb_ymm 已于 2023-02-02 11:09:17 修改 642 收藏 3 分类专栏: java 文章标签: mybatis sql mysql 编辑 版权 java 专栏收录该内容 104 篇文章2 订阅 背景 MyBatis是一...

    struts2+jdbc+eclipse成绩查询系统

    开发者通过编写SQL语句来操作学生成绩表,例如插入新成绩、更新已有成绩、删除无效数据,以及查询特定条件下的成绩信息。 3. **Java编程语言**: Java作为系统的主要开发语言,提供了面向对象的特性,使得代码...

    oracle-jdbc分页实现(只需传入sql语句即可实现分页)

    通过声明游标,设置查询条件,然后在循环中移动游标位置来获取分页数据。这种方式较为复杂,一般不推荐在SQL语句中直接使用,更适合在Java代码中操作。 3. Oracle高级分页: Oracle 12c引入了窗口函数ROW_NUMBER()...

    shardingJdbc功能代码

    ShardingJDBC支持动态数据源,这意味着在运行时可以根据业务条件选择合适的数据源。例如,可以通过读写分离、分片策略等来动态切换数据源,提高系统性能。 **3. SQL路由与执行** ShardingJDBC能够解析SQL语句,并...

    java多线程分页查询

    例如,在一个用户众多的社交平台上,当用户需要查看自己的动态列表时,如果每次都是实时查询数据库并返回所有数据,不仅效率低下,还会给服务器带来巨大的压力。因此,采用一种能够预先查询数据,并且能够快速响应...

    impala-jdbc驱动

    6. **性能优化**:利用JDBC驱动,可以根据网络条件、数据量等因素调整查询参数,例如设置批大小、超时限制等。 7. **安全连接**:支持SSL加密,确保数据传输过程中的安全性,同时支持Kerberos等认证机制,增强系统...

    jdbc的lib.zip

    4. **SqlProvider**:用于动态构建SQL语句,可以根据条件自动生成SQL。 5. **Transaction Management**:Spring提供了声明式事务管理,通过配置即可控制事务的边界,无需在代码中显式调用开始、提交或回滚事务。 *...

    jsp+JDBC留言板

    - 查询留言:使用`SELECT`语句获取所有或特定留言,可能还会涉及到按照时间、ID等条件进行排序。 - 更新留言:虽然不是必需,但系统可能提供修改留言的功能,此时需要`UPDATE`语句。 - 删除留言:用户也可能有删除...

    sqljdbc Jar包

    2. **本地化资源**:可能还会包含不同语言版本的本地化文件,如`sqljdbc_auth.dll`,这是一个用于集成Windows身份验证的动态链接库。根据操作系统和语言环境的不同,可能有多个版本。在Windows平台上,这个库文件...

    JavaWeb查询分页的例子,查询条件存储

    在这个例子中,我们使用了JSP(JavaServer Pages)和Servlet来实现这个功能,同时解决了查询条件的存储以及多条件查询的问题。 首先,JSP是一种动态网页技术,它允许我们在HTML页面中嵌入Java代码,使得服务器端...

    jdbc操作数据库分页

    在实际开发中,我们通常会封装一个数据库操作工具类,提供分页查询的方法,参数包括表名、查询条件、排序字段、页码和每页大小。这样可以使代码更简洁,复用性更强。 总结来说,JDBC分页主要是通过构造带有LIMIT和...

    hibernate实现动态SQL查询

    在Hibernate中,我们通常使用HQL(Hibernate Query Language)或Criteria API进行查询,但这些方式并不支持复杂的动态查询。为了实现动态SQL,我们可以借助于Hibernate的QBC(Query By Criteria)和Criteria API,...

    泛型封装JDBC

    这样,我们可以在运行时动态构建SQL语句,实现任意数量的查询条件。 6. **自定义适配器**: 为了适应MySQL或其他数据库,我们可以设计一个适配器模式。创建一个抽象的`DatabaseAdapter`接口,然后为每种数据库实现...

    jdbc.rar_JDBC增删改查_java jdbc_jdbc_jdbc 增删改查_jdbc封装

    Statement适用于静态SQL,而PreparedStatement适用于动态SQL,可以防止SQL注入攻击。 4. **执行SQL**:通过Statement或PreparedStatement对象,我们可以调用`executeQuery()`或`executeUpdate()`方法来执行查询或...

    JDBC_Java反射技术入门

    - **动态SQL**:反射可以用于构建动态SQL,比如根据条件动态拼接WHERE子句。 - **数据库元数据**:通过反射获取Connection的DatabaseMetaData,可以获取数据库的表信息、列信息等,用于自动生成SQL语句或ORM框架。...

Global site tag (gtag.js) - Google Analytics