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

Spring框架下如何用Java正确校验查询条件是否为空?

解决Spring查询条件空值校验及SQL逻辑错误问题

咱们先梳理下你遇到的核心问题:空值判断逻辑不严谨导致无法正确识别空查询条件,加上isEmpty()方法实现不准确,使得明明没有有效查询条件时,代码仍会进入WHERE分支甚至触发ID相关逻辑。下面一步步来修复:

1. 替换错误的字符串空值判断逻辑

你代码里用data.getEmployeeID()!="" && data.getEmployeeID()!=null来判断员工ID是否非空,这有两个明显问题:

  • 判断顺序错误:应该先检查!=null,虽然Java中null != ""不会抛异常,但不符合代码规范,也容易混淆
  • 没处理空白字符串:比如用户输入全空格的字符串,isEmpty()会返回false,但实际是无效输入

推荐用Spring自带的org.springframework.util.StringUtils.hasText()工具方法,它会同时校验null、空字符串和全空白字符串:

if(StringUtils.hasText(data.getEmployeeID())) {
    criteria.add(CRITERIA_EMPLOYEEID2);
    System.out.println("Employee IDs");
    input_empID = true;
}

员工姓名的判断也同步改成:

if(StringUtils.hasText(data.getEmployeeName())) {
    criteria.add(nameCriteriaHelper(data.getEmployeeName()));
    System.out.println("Employee Name AKOOO");
    input_empName = true;
}

2. 修复EmployeeSearchDto.isEmpty()方法

你提到isEmpty()无法准确判定空条件,大概率是这个方法的实现逻辑有问题。比如它可能只检查了部分字段,或者判断逻辑写反了。正确的isEmpty()应该检查所有查询字段是否都处于空/默认状态:

假设你的EmployeeSearchDto结构如下,对应的isEmpty()实现参考:

public class EmployeeSearchDto {
    private String employeeID;
    private String employeeName;
    private Integer departmentID;
    private Integer positionID;
    private Integer workplaceID;

    public boolean isEmpty() {
        return !StringUtils.hasText(employeeID)
                && !StringUtils.hasText(employeeName)
                && (departmentID == null || departmentID == 0)
                && (positionID == null || positionID == 0)
                && (workplaceID == null || workplaceID == 0);
    }
}

(如果你的字段默认值不是0,记得对应调整判断逻辑)

3. 优化SQL拼接,避免无效WHERE子句

当所有查询条件都为空时,原来的代码会拼接出WHERE但后面没有任何条件,直接导致SQL语法错误。可以调整逻辑:只有当criteria列表不为空时,才添加WHERE子句:

// 替换原来的if(!data.isEmpty())块
if(!criteria.isEmpty()) {
    query = query.concat("WHERE ");
    query = query.concat(String.join(" OR ", criteria));
}

这样即使isEmpty()判断有误,只要没有有效条件,就不会生成无效的WHERE子句。

4. 修复ID为null时的逻辑触发问题

原来的判断data.getEmployeeID()!="" && data.getEmployeeID()!=null,当employeeID是null时,data.getEmployeeID()!=""是true,但data.getEmployeeID()!=null是false,理论上不会触发ID逻辑。但如果isEmpty()误判为非空,就会进入WHERE分支导致SQL错误。用上面的StringUtils.hasText()和优化后的SQL拼接逻辑,就能彻底避免这个问题。

修改后的核心代码片段

public List<Object> searchEmployee(EmployeeSearchDto data) {
    Session session = sessionFactory.openSession();
    final String CRITERIA_EMPLOYEEID = "emp.employeeID =:id";
    final String CRITERIA_EMPLOYEEID2 = "emp.employeeID LIKE:id";
    final String CRITERIA_POSITION= "emp.positionID =:posID";
    final String CRITERIA_DEPARTMENT="emp.departmentID =:deptID";
    final String CRITERIA_WORKPLACE = "emp.workplaceID =:workID";
    Boolean selected_dept = false;
    Boolean selected_pos = false;
    Boolean selected_work = false;
    Boolean input_empID = false;
    Boolean input_empName = false;
    // 把全局临时变量改成方法局部变量,避免线程安全问题
    String firstName = "";
    String middleName = "";
    String lastName = "";
    String completeName = "";
    String firstLastName = "";
    boolean searchbyOne = false;
    boolean searchbyFandL = false;
    boolean searchbyCompName = false;
    List<String> criteria = new ArrayList<>();
    List<Object> employees = null;

    try{
        String query = "Select emp.employeeID, emp.firstName, emp.middleName, emp.lastName, " +
                "pos.positionName, dept.deptName, work.workplaceName " +
                "from Employee emp " +
                "INNER JOIN Department dept ON emp.departmentID = dept.deptID " +
                "INNER JOIN Position pos ON emp.positionID = pos.positionID " +
                "INNER JOIN Workplace work ON emp.workplaceID = work.workplaceID ";

        // 逐个检查查询字段
        if(StringUtils.hasText(data.getEmployeeID())) {
            criteria.add(CRITERIA_EMPLOYEEID2);
            System.out.println("Employee IDs");
            input_empID = true;
        }
        if(StringUtils.hasText(data.getEmployeeName())) {
            criteria.add(nameCriteriaHelper(data.getEmployeeName()));
            System.out.println("Employee Name AKOOO");
            input_empName = true;
        }
        if(data.getDepartmentID() != null && data.getDepartmentID() != 0) {
            criteria.add(CRITERIA_DEPARTMENT);
            System.out.println("Dept ID ");
            selected_dept = true;
        }
        if(data.getPositionID() != null && data.getPositionID() != 0) {
            criteria.add(CRITERIA_POSITION);
            System.out.println("POS ID ");
            selected_pos = true;
        }
        if(data.getWorkplaceID() != null && data.getWorkplaceID() != 0) {
            criteria.add(CRITERIA_WORKPLACE);
            System.out.println("Work ID ");
            selected_work = true;
        }

        // 只有存在有效条件时才添加WHERE
        if(!criteria.isEmpty()) {
            query = query.concat("WHERE ");
            query = query.concat(String.join(" OR ", criteria));
        }

        query = query.concat(" ORDER BY emp.joinDate DESC");
        System.out.println("QUERY: " + query);
        Query q = session.createQuery(query);

        if(input_empID) {
            q.setParameter("id", "%" + data.getEmployeeID() + "%");
        }
        if(input_empName) {
            if(searchbyOne) q.setParameter("inputName", "%" + data.getEmployeeName() + "%");
            if(searchbyFandL) q.setParameter("firstLastName", "%" + firstLastName+ "%");
            if(searchbyCompName) q.setParameter("completeName", "%" + completeName+ "%");
        }
        if(selected_dept) {
            q.setParameter("deptID", data.getDepartmentID());
        }
        if(selected_pos) {
            q.setParameter("posID", data.getPositionID());
        }
        if(selected_work) {
            q.setParameter("workID", data.getWorkplaceID());
        }

        employees = (List<Object>) q.list();
    }catch(Exception e){
        e.printStackTrace();
    }finally{
        session.close();
    }
    return employees;
}

额外小建议

  • 尽量避免手动拼接SQL,容易出现语法错误和SQL注入风险,推荐用Hibernate Criteria API或者Spring Data JPA的Specification构建动态查询
  • 不要用全局变量存储查询临时数据(比如firstName、searchbyOne),多线程环境下会出现数据错乱

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:55:03