【问题标题】:Querying mysql with java with multiple possible "where" statements使用带有多个可能的“where”语句的 java 查询 mysql
【发布时间】:2018-10-16 00:10:55
【问题描述】:

我正在尝试为使用 java 和 mysql 数据库构建的电影过滤系统找到一个很好的解决方案。用户应该能够根据许多属性过滤他们希望看的电影,例如:导演、演员、长度、流派、年份……。总共有 11 个字段可用于过滤查询。

问题是其中一些字段可以(并且可能会)留空。例如,也许用户只想根据某种类型、导演和长度过滤数据。或者他们可能只想根据制作工作室过滤它,而不关心其他过滤器选项。

我已与服务器建立连接,问题在于创建将在statement.executeQuery(SQL_String) 中使用的“SQL_String”。

假设我只想过滤一个字段。然后我知道我可以写了

String field = //user input (for example: actor)
String filter = //user input (for example: 'tom cruise')
String SQL_String = "SELECT * FROM Movies WHERE "+field + "=" +filter

但如果我想让用户根据几个(或零个)字段进行过滤,那么我不知道如何编写代码。

一些示例查询可能是:

"SELECT * FROM Movies WHERE (director = 'steven spielberg' AND genre = 'action' AND length >100)"

"SELECT * FROM Movies WHERE (type = 'tv-series' AND actor = 'bob odenkirk')"

所以用户可以指定他们想要过滤的字段(如果有的话),我需要提出一个可以考虑这些字段并构造查询字符串的 java 代码。

【问题讨论】:

  • 对于可选参数 sql 范例,我建议使用 CriteriaBuilder
  • 顺便说一句,即使您决定继续使用上面的SQL,也不应该简单地附加列和值,因为这有 SQL 注入攻击的风险
  • 在应用中不要使用*,否则会出问题..
  • 使用 CONCAT(attribute1,attribute2,...,11) LIKE(userinput1%userinput2%...%11) 可以吗?其中attribute1 可以是actor,如果用户不想根据它进行过滤,则userinput1 可以为空,或者如果他们确实想过滤它,则为'tom Cruise'。

标签: java mysql where


【解决方案1】:

由于您不知道用户将过滤多少个字段,但您确实知道您正在处理的数据有两个部分(字段和过滤器),所以我想到的前两件事是映射和元组。因为,与 Python 不同,Java 没有内置的元组数据类型(据我所知),这里有一个小示例解决方案,我想到了使用 Java 的 HashMap 和 Map 类解决您的问题。

在此示例中,我创建了一个 HashMap,其中键是“字段”的字符串,值是“过滤器”的字符串。您可以根据代码中的任何位置的用户输入设置这些值(在此示例中,只是在 main 方法中硬编码)。然后,您可以遍历 HashMap (see this helpful post) 中的键值对,附加键和值以及查询所需的其他字符。这是一个简单的示例,但显示了可能的解决方案。

如果您想确保此解决方案适用于过滤值为整数的情况,则只需在循环中添加另一个 if 语句以尝试解析整数,如果存在则不添加额外的\' 转义字符。

import java.util.HashMap;
import java.util.Map;

public class MovieQueryTest {
  public static void main(String[] args) {

    String SQL_Query = "SELECT * FROM Movies WHERE ";

    HashMap<String, String> queryFilters = new HashMap<>();

    queryFilters.put("director", "Steven Spielberg");
    queryFilters.put("type", "tv-series");
    queryFilters.put("actor", "Bob Odenkirk");

    boolean firstQueryFilter = true;

    for (Map.Entry<String, String> entry : queryFilters.entrySet()) {
      if (firstQueryFilter) {
        SQL_Query += entry.getKey() + "=\'" + entry.getValue() + "\'";
        firstQueryFilter = false;
      } else {
        SQL_Query += " AND " + entry.getKey() + "=\'" + entry.getValue() + "\'";
      }

    }

    System.out.println(SQL_Query);

  }
}

【讨论】:

    猜你喜欢
    • 2012-01-28
    • 1970-01-01
    • 2017-12-09
    • 1970-01-01
    • 1970-01-01
    • 2018-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多