我在Spring中爲項目創建REST API。春季地圖可選查詢參數到SQL準備語句
我面臨的問題是如何優雅地創建一個帶有可變數量參數的PreparedStatement。
例如,我有一個產品的收集和我有很多的查詢參數
/賬戶?的categoryId =不便&爲了= ASC &價格= 上限= 10 &偏移= 300
問題是,這些參數可能會或可能不會設置。
目前,我有一些看起來像這樣,但我還沒有開始消毒用戶輸入
控制器
@RequestMapping(method = RequestMethod.GET)
public List<Address> getAll(@RequestParam Map<String, String> parameters) {
return addressRepository.getAll(parameters);
}
庫
@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());
}
我能提高嗎?或者,還有更好的方法?
這種方法的另一個問題是,我失去的參數類型安全。作爲收集資源,我必須分頁。每次查詢參數映射時,我都必須檢查它是否爲LIMIT或OFFSET,並將參數值轉換爲long。我必須爲每個允許的參數附加一組規則。我是否讓這個過於複雜? – 2014-12-06 07:57:35
是的,我認爲你讓它變得複雜:)。您原來的方法中也丟失了類型安全性,主要是因爲您收到一個Map作爲參數。爲此,您可以嘗試@QueryParam,但namedParameters貼圖仍然必須是Map 。如果你想使地圖類型安全,那麼在編寫適用於所有參數的通用代碼時就會失敗。 –
2014-12-06 10:39:37