Java / JDBC - 多参数搜索最佳实践

时间:2011-02-01 04:28:09

标签: java jdbc

我正在使用以下代码从关系数据库生成搜索结果,具体取决于基于Web的客户端的多个(可选)搜索参数。

目前我正在使用“java.sql.Statement”来实现功能,但我需要使用“java.sql.PreparedStatement”来实现相同的功能,以防止SQL注入。

让我知道更改代码的最佳做法


E.g。

来自基于网络的客户的用户输入。

  • param1 - 可选
  • param2 - 可选
  • dateParamFr - 可选
  • dateParamTo - 可选

SQL模式的伪代码取决于搜索参数,如下所示

IF (WITHOUT ANY SEARCH PARAMETER){
    SELECT * FROM TEST_TABLE;
}
ELSE IF(WITH param1){
    SELECT * FROM TEST_TABLE WHERE COLUMN1= param1;
}
ELSE IF(WITH param1 & param2){
    SELECT * FROM TEST_TABLE WHERE COLUMN1= param1 AND  COLUMN2= param2
}
SO ON
………

以下是我的EJB中的Java代码片段

    /* 
        NOTE : Hashtable pSearchParam is a method parameter
    */

    Connection  cnBOP           = null;
    Statement stmt              = null;
    StringBuffer sb             = new StringBuffer("");         

    try {
        cnBOP   = jdbcBOP.getConnection(); // DataSource jdbcBOP
        stmt    = cnBOP.createStatement();

        /* ######################## SQL BODY ######################################*/
        sb.append("SELECT COLUMN1, COLUMN2, DATE_COLUMN ");
        sb.append("FROM TEST_TABLE ");

        /* ######################## SQL WHERE CLAUSE ##############################*/
        if(pSearchParam.size()>=1){
            sb.append("WHERE ");
            Enumeration e = pSearchParam.keys();
            int count =0;

            while(e.hasMoreElements()){
                if (count >=1) sb.append("AND ");

                String sKey = (String) e.nextElement();

                if (sKey.equals("param1"))              sb.append ("COLUMN1 ='"+pSearchParam.get(sKey)+"' ");
                else if (sKey.equals("param1"))         sb.append ("COLUMN2 ='"+pSearchParam.get(sKey)+"' ");                   
                else if (sKey.equals("dateParamFr"))    sb.append ("DATE_COLUMN >= TO_DATE('"+pSearchParam.get(sKey)+" 00:00:00','DD/MM/YYYY HH24:MI:SS') ");
                else if (sKey.equals("dateParamTo"))    sb.append ("DATE_COLUMN <= TO_DATE('"+pSearchParam.get(sKey)+" 23:59:59','DD/MM/YYYY HH24:MI:SS') ");

                count ++;
            }
        }
        /* ######################## SQL ORDER BY CLAUSE ############################*/
        sb.append("ORDER BY DATE_COLUMN DESC");

        ResultSet rs = stmt.executeQuery(sb.toString());

4 个答案:

答案 0 :(得分:4)

而不是

sb.append ("COLUMN1 ='"+pSearchParam.get("param1")+"' ");

你必须这样做

sb.append ("COLUMN1 = ? ");

然后在创建语句后

stmt.setString(1, pSearchParam.get("param1"));

这仅适用于第一个参数,您需要对所有语句执行此操作并枚举

中的索引
setString(int index, String param);

请注意,您需要使用int,long,Date ......等其他方法

答案 1 :(得分:1)

依赖于您的数据库引擎,您可以使用

之类的SQL函数
isnull(value,valueIfNull) 

例如在MSSQL中

select * from Order where storeId = isnull(?,storeId)

下一个java代码

preparedStatement.setNull(1,java.sql.Types.INTEGER)

如果您需要从过滤器或

中省略此参数
preparedStatement.setInt(1,20)

如果您需要找到storeId = 20的所有订单

答案 2 :(得分:0)

这看起来像是Hibernate Criteria Queries ...

的工作
  

Criteria是一个简化的API,用于通过撰写来检索实体   标准对象。 这是非常的   方便的功能方法   像“搜索”屏幕那里有一个   可变数量的条件   放在结果集上。

答案 3 :(得分:0)

你在使用Hibernate吗?然后你可以使用criteria API。对于非休眠,您可以查看SqlBuilder工具以根据条件生成SQL。

你还应该使用标记“?”而不是实际值。

所以这个查询应该是这样的。

SELECT * FROM TEST_TABLE WHERE COLUMN1= ?;

然后,您可以使用PreparedStatements为此列设置值。关于使用PreparedStatement的入门教程是here