spring map optional query parameters to sql prepared statement -
i'm creating rest api in spring project.
the problem i'm facing how elegantly create preparedstatement variable number of parameters.
for eg. have product collection , i'd have lots of query parameters
/accounts?categoryid=smth&order=asc&price=<1000&limit=10&offset=300
problem these parameters may or may not set.
currently have looks this, haven't started sanitizing 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 * addresses inner join (select id addresses " + conditions.tostring() + "limit ? offset ?) results using (id)"; system.out.println(base); return jdbc.query(base, parametervalues.toarray(), new addressrowmapper()); }
can improve this? or there better way?
i found above code hard maintain since has complex logic build clause. spring's namedparameterjdbctemplate used simplify logic. follow this link having @ basic example on namedparameterjdbctemplate
here's how new code should like
public list<address> getall(map<string, string> parameters) { map<string, object> namedparameters = new hashmap<>(); for(string key : parameters.keyset()) { if(allowedparameters.contains(key)) { namedparameters.put(key, parameters.get(key)); } } string sqlquery = buildquery(namedparameters); namedparameterjdbctemplate template = new namedparameterjdbctemplate(null /* data source object */); return template.query(sqlquery, namedparameters, new addressrowmapper()); } private string buildquery(map<string, object> namedparameters) { string selectquery = "select * addresses inner join (select id addresses "; if(!(namedparameters.isempty())) { string whereclause = "where "; (map.entry<string, object> param : namedparameters.entryset()) { whereclause += param.getkey() + " = :" + param.getvalue(); } selectquery += whereclause; } return selectquery + " ) results using (id)"; }
Comments
Post a Comment