Java 优雅地处理SQL空参数

Java 优雅地处理SQL空参数,java,android,sql,sqlite,Java,Android,Sql,Sqlite,我通过检查提交到查询的每个列字段是否为空==null来生成SQL语句。我的方法似乎很幼稚,所以我想知道如何优雅地处理空参数。当没有指定某个内容时,它应该简单地匹配任何内容 代码如下: public List<Flight> findMatchingFlights(Flight flight) { List<Flight> foundFlights = new ArrayList<>(); StringBuilder sqlQueryBuilde

我通过检查提交到查询的每个列字段是否为空==null来生成SQL语句。我的方法似乎很幼稚,所以我想知道如何优雅地处理空参数。当没有指定某个内容时,它应该简单地匹配任何内容

代码如下:

public List<Flight> findMatchingFlights(Flight flight)
{
    List<Flight> foundFlights = new ArrayList<>();
    StringBuilder sqlQueryBuilder = new StringBuilder();
    sqlQueryBuilder.append("SELECT * FROM Flights");
    boolean emptyQuery = true;

    if(flight.getDeparture() != null)
    {
        if(emptyQuery)
        {
            sqlQueryBuilder.append(" WHERE ");
            emptyQuery = false;
        }

        sqlQueryBuilder.append("Departure = '" + flight.getDeparture() + "'");
    }

    if(flight.getArrival() != null)
    {
        if(emptyQuery)
        {
            sqlQueryBuilder.append(" WHERE ");
            emptyQuery = false;
        }
        else
        {
            sqlQueryBuilder.append(" AND ");
        }

        sqlQueryBuilder.append("Arrival = '" + flight.getArrival() + "'");
    }

    if(flight.getFlightNumber() != null)
    {
        if(emptyQuery)
        {
            sqlQueryBuilder.append(" WHERE ");
            emptyQuery = false;
        }
        else
        {
            sqlQueryBuilder.append(" AND ");
        }

        sqlQueryBuilder.append("Number = '" + flight.getFlightNumber() + "'");
    }

    if(flight.getFlightMinutes() != 0)
    {
        if(emptyQuery)
        {
            sqlQueryBuilder.append(" WHERE ");
            emptyQuery = false;
        }
        else
        {
            sqlQueryBuilder.append(" AND ");
        }

        sqlQueryBuilder.append("Duration = " + flight.getFlightMinutes());
    }

    /*
    ...
    A bunch more fields
    */

    if(flight.getAirplane() != null)
    {
        if(emptyQuery)
        {
            sqlQueryBuilder.append(" WHERE ");
        }
        else
        {
            sqlQueryBuilder.append(" AND ");
        }

        sqlQueryBuilder.append("Airplane = '" + flight.getAirplane() + "'");
    }

    sqlQueryBuilder.append(";");

    // Execute sql and fill list with rows that match
}

您可以为下面的块创建公共方法,并通过传递参数来调用该方法

if(flight.getArrival() != null)
    {
        if(emptyQuery)
        {
            sqlQueryBuilder.append(" WHERE ");
            emptyQuery = false;
        }
        else
        {
            sqlQueryBuilder.append(" AND ");
        }

        sqlQueryBuilder.append("Arrival = '" + flight.getArrival() + "'");
    }

最好的方法是在SQL中执行此操作,而不是在Java中检查null。这就是你能做到的

sqlQueryBuilder.append("(Number = '" + flight.getFlightNumber() + "' OR " + flight.getFlightNumber() + " IS NULL)");
这样,您就不必在java中检查null,如果flight.getFlightNumber为null,那么where子句将始终返回true,这是您想要的

这种方法的唯一缺点是查询中将包含子句,但由于您打算使用这些列来查询表,以防它们不为null,因此我假设表也将被索引

sqlQueryBuilder.append("SELECT * FROM Flights WHERE 1 = 1");
然后,您不需要emptyQuery标志和检查以及许多if-else构造

List<Flight> foundFlights = new ArrayList<>();
    StringBuilder sqlQueryBuilder = new StringBuilder();
    sqlQueryBuilder.append("SELECT * FROM Flights WHERE 1 = 1");

    if(flight.getDeparture() != null) {
        sqlQueryBuilder.append("AND Departure = '" + flight.getDeparture() + "'");
    }

我不认为这里的担心是检查emptyQuery,这里的担心是检查提交给查询的列字段是空的还是空的。hi@Johnson Abraham,这是加快代码审查的速度,以及在没有SQL提示的情况下减少代码量的方法,也可以在java方面做这项工作。此外,还可以使提供的代码更加优雅。顺便说一句,我认为你的解决方案比我的好。不完全是。此代码段修改了两个变量,这使得无法提取该方法。此外,还涉及不同的数据类型,如int,其处理方式与String稍有不同…您确定flight.getFlightNumber应该位于OR子句中的字符串内,而不是实际的Java方法调用吗?没错,应该追加值,用正确的答案更新了答案。这样的或表达式通常不能用索引进行优化。@CL。当您做出这样的陈述时,请提供相关的参考,而不是误导。特别是在这种情况下,OR子句的第二部分没有涉及任何列。@CL.引用您发送的URL。分析每个子项时,将其视为整个WHERE子句,以查看该子项是否可自行索引。如果OR子句的每个子项都是可单独索引的,则可以对OR子句进行编码,以便使用单独的索引来评估OR子句的每个项。因此,即使是文档也不会声明您所声明的内容。在回答中,我并没有说这个问题会很快被提出。我所说的是,如果表被索引,它就不会那么慢了。我完全不理解否决票,因为这不是我要问的问题。