I'm creating a REST API in Spring for a project.
The problem I'm facing is how to elegantly create a PreparedStatement with variable number of parameters.
For eg. I have a product collection and I'd have lots of query parameters
/accounts?categoryId=smth&order=asc&price=<1000&limit=10&offset=300
Problem is that these parameters may or may not be set.
Currently I have something that looks like this, but I haven't even started sanitizing for user input
Controller
@RequestMapping(method = RequestMethod.GET)
public List<Address> getAll(@RequestParam Map<String, String> parameters) {
return addressRepository.getAll(parameters);
}
Repository
@Override
public List<Address> getAll(Map<String, String> parameters) {
StringBuilder conditions = new StringBuilder();
List<Object> parameterValues = new ArrayList<Object>();
for(String key : parameters.keySet()) {
if(allowedParameters.containsKey(key) && !key.equals("limit") && !key.equals("offset")) {
conditions.append(allowedParameters.get(key));
parameterValues.add(parameters.get(key));
}
}
int limit = Pagination.DEFAULT_LIMIT_INT;
int offset = Pagination.DEFAULT_OFFSET_INT;
if(parameters.containsKey("limit"))
limit = Pagination.sanitizeLimit(Integer.parseInt(parameters.get("limit")));
if(parameters.containsKey("offset"))
offset = Pagination.sanitizeOffset(Integer.parseInt(parameters.get("offset")));
if(conditions.length() != 0) {
conditions.insert(0, "WHERE ");
int index = conditions.indexOf("? ");
int lastIndex = conditions.lastIndexOf("? ");
while(index != lastIndex) {
conditions.insert(index + 2, "AND ");
index = conditions.indexOf("? ", index + 1);
lastIndex = conditions.lastIndexOf("? ");
}
}
parameterValues.add(limit);
parameterValues.add(offset);
String base = "SELECT * FROM ADDRESSES INNER JOIN (SELECT ID FROM ADDRESSES " + conditions.toString() + "LIMIT ? OFFSET ?) AS RESULTS USING (ID)";
System.out.println(base);
return jdbc.query(base, parameterValues.toArray(), new AddressRowMapper());
}
Can I improve this? Or is there a better way?