caitlinp
caitlinp

Reputation: 183

A substitute to using a counter variable

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

Answers (2)

RealSkeptic
RealSkeptic

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

Arnaud Denoyelle
Arnaud Denoyelle

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

Related Questions