You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何简化多条件查询场景下大量IF语句的使用

简化动态SQL查询生成的方案

问题背景

我有一段代码,允许用户从5个下拉菜单中选择不同参数,选项包括"None"、"Name"、"Manager"、"AccessLevel"、"Inhabitant"和"Location",这些参数会与JTextField中的输入值匹配。目前通过大量嵌套IF语句组合参数生成对应的SQL查询语句,比如同时选择Name、Manager和Location时,生成的SQL语句为:

query = "SELECT * FROM propertyInfo WHERE propertyName = ? AND propertyManager = ? AND propertyLocation = ?";

这种方式导致代码充斥繁杂的判断逻辑,需要编写数百行代码处理不同组合,且后续扩展新参数时成本极高。以下是部分现有代码:

if (searchingForName == true) {
    if (searchingForManager == true) {
        if (searchingForAccessLevel == true) { // final lvl 1
             query = "SELECT * FROM propertyInfo WHERE propertyName = ? AND propertyManager = ? AND accessLevelRequired = ?"; 
             query2 = "SELECT COUNT(*) AS recordCount FROM propertyInfo WHERE  propertyName = ? AND propertyManager = ? AND accessLevelRequired = ?"; 
        }else if ((searchType1.equals("Inhabitant") || searchType2.equals("Inhabitant") || searchType3.equals("Inhabitant"))) { // final lvl 2
          query = "SELECT * FROM propertyInfo WHERE propertyName = ? AND propertyManager = ? AND propertyInhabitant = ?"; 
          query2 = "SELECT COUNT(*) AS recordCount FROM propertyInfo WHERE  propertyName = ? AND propertyManager = ? AND propertyInhabitant = ?"; 
      }else if ((searchType1.equals("Location") || searchType2.equals("Location") || searchType3.equals("Location"))) { // finaly lvl 3
          query = "SELECT * FROM propertyInfo WHERE propertyName = ? AND propertyManager = ? AND propertyLocation = ?"; 
          query2 = "SELECT COUNT(*) AS recordCount FROM propertyInfo WHERE  propertyName = ? AND propertyManager = ? AND propertyLocation = ?"; 
      }
    }  else if ((searchType1.equals("AccessLevel") || searchType2.equals("AccessLevel") || searchType3.equals("AccessLevel"))) { // sub lvl 2
         if ((searchType1.equals("Inhabitant") || searchType2.equals("Inhabitant") || searchType3.equals("Inhabitant"))) { //final lvl 1
          query = "SELECT * FROM propertyInfo WHERE propertyName = ? AND accessLevelRequired = ? AND propertyInhabitant = ?"; 
          query2 = "SELECT COUNT(*) AS recordCount FROM propertyInfo WHERE  propertyName = ? AND accessLevelRequired = ? AND propertyInhabitant = ?"; 
      }else if ((searchType1.equals("Location") || searchType2.equals("Location") || searchType3.equals("Location"))) { // final lvl 2
          query = "SELECT * FROM propertyInfo WHERE propertyName = ? AND accessLevelRequired = ? AND propertyLocation = ?"; 
          query2 = "SELECT COUNT(*) AS recordCount FROM propertyInfo WHERE  propertyName = ? AND accessLevelRequired = ? AND propertyLocation = ?"; 
      }
    } else if ((searchType1.equals("Inhabitant") || searchType2.equals("Inhabitant") || searchType3.equals("Inhabitant"))) { // sub lvl 3
         if ((searchType1.equals("Location") || searchType2.equals("Location") || searchType3.equals("Location"))) { // final lvl 1
          query = "SELECT * FROM propertyInfo WHERE propertyName = ? AND propertyInhabitant = ? AND propertyLocation = ?"; 
          query2 = "SELECT COUNT(*) AS recordCount FROM propertyInfo WHERE  propertyName = ? AND propertyInhabitant = ? AND propertyLocation = ?"; 
    }
         
//}
}else if ((searchType1.equals("Manager") || searchType2.equals("Manager") || searchType3.equals("Manager"))) { // main lvl 2
    
    
    if ((searchType1.equals("AccessLevel") || searchType2.equals("AccessLevel") || searchType3.equals("AccessLevel"))) { // sub lvl 1
        
        
      if ((searchType1.equals("Inhabitant") || searchType2.equals("Inhabitant") || searchType3.equals("Inhabitant"))) {// final lvl 1
           query = "SELECT * FROM propertyInfo WHERE propertyManager = ? AND accessLevelRequired = ? AND propertyInhabitant = ?"; 
           query2 = "SELECT COUNT(*) AS recordCount FROM propertyInfo WHERE   propertyManager = ? AND accessLevelRequired = ? AND propertyInhabitant = ?"; 
           
      }else if ((searchType1.equals("Location") || searchType2.equals("Location") || searchType3.equals("Location"))) { // final lvl 2
          query = "SELECT * FROM propertyInfo WHERE propertyManager = ? AND accessLevelRequired = ? AND propertyLocation = ?"; 
          query2 = "SELECT COUNT(*) AS recordCount FROM propertyInfo WHERE  propertyManager = ? AND accessLevelRequired = ? AND propertyLocation = ?"; 
      }
    }  else if ((searchType1.equals("Inhabitant") || searchType2.equals("Inhabitant") || searchType3.equals("Inhabitant"))) { // sub lvl 2
          if ((searchType1.equals("Location") || searchType2.equals("Location") || searchType3.equals("Location"))) { // final lvl 1
          query = "SELECT * FROM propertyInfo WHERE propertyManager = ? AND propertyInhabitant = ? AND propertyLocation = ?"; 
          query2 = "SELECT COUNT(*) AS recordCount FROM propertyInfo WHERE  propertyManager = ? AND propertyInhabitant = ? AND propertyLocation = ?"; 
      }
    }
  } 
}

简化方案

1. 建立参数与数据库字段的映射

先定义一个静态映射表,将下拉菜单的选项名称对应到数据库实际字段,避免硬编码字段名:

private static final Map<String, String> PARAM_FIELD_MAP = new HashMap<>();
static {
    PARAM_FIELD_MAP.put("Name", "propertyName");
    PARAM_FIELD_MAP.put("Manager", "propertyManager");
    PARAM_FIELD_MAP.put("AccessLevel", "accessLevelRequired");
    PARAM_FIELD_MAP.put("Inhabitant", "propertyInhabitant");
    PARAM_FIELD_MAP.put("Location", "propertyLocation");
}

2. 收集有效查询参数

遍历所有下拉菜单的选择值,过滤掉"None"选项,收集需要参与查询的参数:

// 假设5个下拉菜单的选择值存储在searchTypes列表中
List<String> selectedParams = new ArrayList<>();
for (String type : searchTypes) {
    if (!"None".equals(type)) {
        selectedParams.add(type);
    }
}

3. 动态生成SQL语句

根据收集到的参数,拼接WHERE子句,同时准备参数值列表(用于后续PreparedStatement绑定):

List<String> whereClauses = new ArrayList<>();
List<Object> paramValues = new ArrayList<>();

for (String param : selectedParams) {
    String fieldName = PARAM_FIELD_MAP.get(param);
    whereClauses.add(fieldName + " = ?");
    // 替换为实际获取对应JTextField输入值的逻辑,比如用map存储参数与输入框的对应
    paramValues.add(getInputValueForParam(param)); 
}

// 构建主查询
StringBuilder queryBuilder = new StringBuilder("SELECT * FROM propertyInfo");
if (!whereClauses.isEmpty()) {
    queryBuilder.append(" WHERE ").append(String.join(" AND ", whereClauses));
}
String query = queryBuilder.toString();

// 构建计数查询
StringBuilder countQueryBuilder = new StringBuilder("SELECT COUNT(*) AS recordCount FROM propertyInfo");
if (!whereClauses.isEmpty()) {
    countQueryBuilder.append(" WHERE ").append(String.join(" AND ", whereClauses));
}
String query2 = countQueryBuilder.toString();

4. 绑定参数并执行查询

使用PreparedStatement绑定参数值,避免SQL注入风险:

// 执行主查询
PreparedStatement stmt = connection.prepareStatement(query);
for (int i = 0; i < paramValues.size(); i++) {
    stmt.setObject(i + 1, paramValues.get(i));
}
ResultSet rs = stmt.executeQuery();

// 执行计数查询
PreparedStatement countStmt = connection.prepareStatement(query2);
for (int i = 0; i < paramValues.size(); i++) {
    countStmt.setObject(i + 1, paramValues.get(i));
}
ResultSet countRs = countStmt.executeQuery();

方案优势

  • 代码简洁:彻底消除嵌套IF逻辑,代码量大幅减少
  • 易扩展:新增查询参数只需在映射表中添加条目,无需修改核心逻辑
  • 安全性:采用PreparedStatement绑定参数,从根源避免SQL注入
  • 可维护性:参数与字段的映射集中管理,便于后续修改

内容的提问来源于stack exchange,提问作者Thomas Humphreys

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 14:10:33