Я хочу создать собственный искатель (будучи ветераном веб-разработки, но в то же время полным новичком в Java, Spring и Roo).
Первый метод ниже из моего класса контроллера вида «Актив».Это то, что происходит при первом обращении к странице администрирования активов - она возвращает представление и пакет активных в настоящее время активов.Он работает нормально:
@RequestMapping("/assets")
public ModelAndView listAssets() {
ModelAndView mav = new ModelAndView();
mav.setViewName("admin/asset");
Collection<com.myapp.model.Asset> assets = com.myapp.model.Asset.findAllAssets() ;
mav.addObject("assets", assets);
return mav;
}
Так что теперь я хочу, чтобы запрос POST к этому URL принимал отправку формы поиска актива, которая содержит поля для нескольких ключевых свойств объекта Asset.
(Прямо сейчас я кодирую этот искатель в своем контроллере представления, и я знаю, что в конечном итоге я хочу перенести это в класс модели. Сейчас я просто работаю здесь для удобства.Кроме того, я знаю, что мне не нужно давать полностью определенное имя объекта, я по-новому назвал мой контроллер тем же именем, что и модель, с которой он разговаривает, так что пока я не разберусь с этим, я работаю над этим.)
Я позаимствовал некоторый код у некоторых создателей Roo, которые я сгенерировал, и получил:
@RequestMapping(value = "/assets", method = RequestMethod.POST)
public ModelAndView searchAssets(
@RequestParam("category") String category,
@RequestParam("year") String year,
@RequestParam("manufacturer") String manufacturer,
@RequestParam("drive_type") String driveType,
@RequestParam("subcategory") String subcategory,
@RequestParam("serial") String serial,
@RequestParam("listing_type") String listingType,
@RequestParam("hours") String hours,
@RequestParam("model") String model,
@RequestParam("mileage") String mileage ) {
ModelAndView mav = new ModelAndView();
mav.setViewName("admin/asset");
EntityManager em = com.myapp.model.Asset.entityManager();
TypedQuery<Asset> q = em.createQuery("SELECT o FROM Asset AS o ", Asset.class);
Collection<Asset> assets = q.getResultList();
mav.addObject("assets", assets);
return mav;
}
Итак, вопросы:
1) Есть лиспособ получить коллекцию моих параметров, а не запекать их в сигнатуру метода?Потому что я как бы ненавижу это.
2) Есть ли способ перебрать мои параметры и сгенерировать предложение WHERE моей строки запроса таким образом?Мне бы не хотелось много знать о полях, которые мне здесь дают, и я должен быть в состоянии справиться с этим, у меня в основном не будет всех из них.Поэтому я предпочел бы просто строить свой запрос итеративно, а не декларативно, если это имеет смысл.
Как вы могли бы построить здесь оператор выбора?
РЕДАКТИРОВАТЬ (Решение):
@ madth3 указал мне правильное направление здесь.Вот чем я закончил, и я очень горжусь этим:
public static TypedQuery<Asset> findAssetsByWebRequest( WebRequest request) {
ArrayList<String> wheres = new ArrayList<String>();
Iterator<String> i = request.getParameterNames();
while (i.hasNext()) {
String fieldname = i.next();
String value = request.getParameter(fieldname);
if (value.length() == 0) {
continue;
}
if (fieldname.equals("manufacturer") || fieldname.equals("model") ) {
value = value.replace('*', '%');
if (value.charAt(0) != '%') {
value = "%" + value;
}
if (value.charAt(value.length() - 1) != '%') {
value = value + "%";
}
wheres.add(" o." + fieldname + " LIKE '" + value + "'");
}
else if (fieldname.contains("min")) {
fieldname = fieldname.replace("min", "").toLowerCase();
wheres.add(" o." + fieldname + " >= '" + value + "' ");
}
else if (fieldname.contains("max")) {
fieldname = fieldname.replace("max", "").toLowerCase();
wheres.add(" o." + fieldname + " <= '" + value + "' ");
}
else {
wheres.add(" o." + fieldname + " = '" + value + "' ");
}
}
String query = "SELECT o FROM Asset AS o ";
if (wheres.size() > 0) {
query += " WHERE ";
for (String clause: wheres) {
query += clause + " AND ";
}
query += " 1 = 1 ";
}
EntityManager em = Asset.entityManager();
TypedQuery<Asset> q = em.createQuery(query, Asset.class);
return q;
}
Очевидно, что его нужно параметризировать, чтобы избежать атаки SQL-инъекцией, но это здорово, что он (почти) не должен знатьчто-нибудь о данных, которые ему дают, что он просто соберет запрос из полей, которые ему дали.Нужно знать, с какими полями он работает, с какими полями "как" и "равно", как обращаться с полями "min" и "max", которые определяют диапазон, и т. Д. Но это не так уж плохо.