0

我想使用 MessageFormat 生成 SQL,以便许多用户可以使用相同的字符串,他们只需要传递 where 子句参数。

例如,我想从用户中选择 *,其中 name='John' and age=15 and area='JStreet'

我可以使用 MessageFormat.format(select * from user where {0}={1} and {2}={3} and {4}={5} ,"name","'John'","age ","15","面积","'JStreet'")

但我希望它是动态的。意味着在这里我被限制到 {0}-{5} 如果我需要添加更多 AND 条件怎么办。我怎样才能做到这一点 ?

4

1 回答 1

0

不要让用户将列名指定为字符串。这使您的代码很容易被破解,并且它使您面临一个非常常见且危险的安全漏洞,即 SQL 注入。我知道你说它只是“供内部使用”,但员工/学生可能是黑客,并且总是有可能希望造成伤害。

相反,将列表示为枚举值。我假设表的列user是固定的,因此您可以在枚举中对它们进行硬编码:

public enum UserField {
    NAME,
    AGE,
    AREA
}

正如其他人所提到的,在使用来自最终用户或未知代码的值时,请始终使用 PreparedStatement。您现在可以使用枚举来构建 PreparedStatement:

public PreparedStatement createStatement(Map<UserField, ?> values,
                                         Connection conn)
throws SQLException {

    Collection<String> tests = new ArrayList<>(values.size());
    for (UserField field : values.keySet()) {
        tests.add(field.name().toLowerCase() + "=?");
    }

    String sql;
    if (tests.isEmpty()) {
        sql = "select * from user";
    } else {
        sql = "select * from user where " + String.join(" and ", tests);
    }

    PreparedStatement statement = conn.prepareStatement(sql);

    int index = 0;
    for (Object value : values) {
        statement.setObject(++index, value);
    }

    return statement;
}
于 2020-03-03T12:14:00.773 回答