Reputation: 183
I have a piece of code that works, however, I wanted to know if it was possible to make it better without using a counter variable. I have a map of "filters" and if there's at least one thing in the map i want to mutate my SQL string.
StringBuilder sb = new StringBuilder("SELECT * from Table");
if (filters.size() >= 1) {
int counter = 0; //I don't want to use this
for (String key : filters.keySet()) {
if (counter == 0) {
sb.append(" WHERE " + key + "=?");
counter= 1;
continue;
}
sb.append(" AND " + key + "=?");
}
}
Upvotes: 0
Views: 263
Reputation: 34648
You can use a string joiner, which allows setting an empty value, which will allow you to not include the "WHERE" when your set is empty.
StringJoiner joiner = new StringJoiner(" AND ", " WHERE ", "");
joiner.setEmptyValue("");
filters.keySet().stream().map( key -> key + " = ?" ).forEach(joiner::add);
String query = "SELECT * FROM TABLE" + joiner.toString();
Alternative without stream:
StringJoiner joiner = new StringJoiner("=? AND ", " WHERE ", "=?");
joiner.setEmptyValue("");
filters.keySet().forEach(joiner::add);
String query = "SELECT * FROM TABLE" + joiner.toString();
Upvotes: 1
Reputation: 31283
Note: The request is vulnerable to SQL injection if keys are provided by a client. They should be sanitized.
You can use the "1 = 1"
trick.
StringBuilder sb = new StringBuilder("SELECT * from Table WHERE 1 = 1");
for(String key : filters.keySet()){
sb.append(" AND " + key + "=?");
}
(same goes with "0 = 1"
if you want to chain some OR
statements instead).
Upvotes: 2