SPRING MVC search form

0

Chcę udostępnić możliwość przeszukiwania bazy danych w swoim CRUDzie. Apka ma kilka beanów, min. payment i contact. Obydwa beany mają field o nazwie 'name'. Zrobiłem tabelkę w jsp gdzie każdy TR to osobny formularz.

<tr>
		<td><spring:message code="search.tableRowPaymentByName" /></td>
		<sf:form method="post" action="${pageContext.request.contextPath}/searchpaymentbyname" commandName="payment">
			<td><sf:input path="name" type="text" /></td>
			<td><input class="formButton" type="submit" value="<spring:message code='button.search'/>" /></td>
			<td><div class="errors"><sf:errors path="name" /></div></td>
		</sf:form>
	</tr>
	<tr>
		<td><spring:message code="search.tableRowContact" /></td>
		<sf:form method="post" action="${pageContext.request.contextPath}/searchcontact" commandName="contact">
			<td><sf:input path="name" type="text" /></td>
			<td><input class="formButton" type="submit" value="<spring:message code='button.search'/>" /></td>
			<td><div class="errors"><sf:errors path="name" /></div></td>
		</sf:form>
	</tr>

Controller, który zwraca widok wygląda:

Controller
public class TimetableController {

	@RequestMapping("/")
	public String showHome(Payment payment, Contact contact){
		return "home";
	}

Przykładowo, jeśli user zechce poszukać paymentu po nazwie, to uruchomi się ta metoda PaymentControllera:

@RequestMapping(value = "/searchpaymentbyname")
	public String searchPaymentByName(Model model, Payment payment, BindingResult rs, Contact contact) {

		List<Payment> result = null;

		if (payment.getName().isEmpty()) {
			return "redirect:/payments";
		}
		result = paymentService.findByName(payment.getName());

		if (result.size() < 1) {
			rs.rejectValue("name", "search.paymentByName.notFound");
			return HOME;
		} else {
			model.addAttribute(ALL_PAYMENTS, result);
			return PAYMENTS;
		}
	}

Problem pojawia się w chwili, kiedy zostanie wprowadzona fraza, dla której nie ma wyników, czyli ta część kodu zostanie wykonana:

if (result.size() < 1) {
			rs.rejectValue("name", "search.paymentByName.notFound");
			return HOME;

Komunikat o braku wyników wyświetli się prawidłowo, wrócimy z powrotem do widoku z formularzem, natomiat zarówno input dla pola 'name' z Payment jak i dla pola 'name' z Contact będą miały wartość taką, jak wklepana uprzednio w inpucie Payment. Oczywiście wygląda to dokładnie tak samo w drugą stroną. Idzie oczywiście o to, żeby owszem, user wrócił do widoku z formularzem i zastał wklepaną przez siebie frazę wraz z informacją o tym, iż dla niej nie ma rezultatów w bazie dannych, natomiast niech ta wartość będzie wyłącznie w tym inpucie, w którym została pierwotnie wklepana.

Przy okazji chciałem zapytać, o to jak najsensowniej wykonać taki formularz szukający, w sytuacji, gdzie mamy kilka beanów z różnymi polami. Ta moja obecna wersja z całą pewnością ma dość chałupniczy charakter, ale tak to jest, jak się człowiek dopiero uczy. Póki co mam osobny button dla każdego fieldu, bo myślałem, że dodanie jednego przycisku bedzie problematyczne o tyle, o ile z wieloma inputami textowymi i jednym przyciskiem należałoby wprowadzić wiele if'ów (co w sytuacji, gdzie wklepano dane w więcej niż jeden input text itd.).

0

Znalazłem rozwiązanie.

Spring, mimo informacji w postaci,
<form:from modelAttribute=jakiś bean>
zwraca wklepane dane dla wszystkich inputów, które mają taki sam path, jak input, do którego wklepano dane.
<form input path="jakieś pole beana">
W przykładzie, który zamieściłem powyżej miałem kilka form z różnymi beanami, jednak beany te miały pola o takiej samej nazwie - zarówno Payment miał pole 'name', jak i Contact miał swoje pole "name".

Więc mimo, że formy wyglądały tak:

<form:input path="name"...>
</ form:form>
<form form modelAttribute="contact"...>
<form:input path"name"...>
</form:form>```

To kiedy odpaliła się ta część z Controllera

```if (result.size() < 1) {
            rs.rejectValue("name", "search.paymentByName.notFound");
            return HOME;```

w formularzu, zarówno w inpucie, za którym stoi modelAttribute="payment", jak i każdym innym inpucie z path="name", Spring zwracał wklepany rezultat. 


 Na dwa sposoby, a przynajmniej tyle znam ja, można rozwiązać ten problem. 

1. Wystarczy zmienić pola w klasach, zamiast pola "name" w klasie Payment można dać pole o nazwie "paymentName", wtedy "pathy" nie będą nam się powtarzać i wklepana wartość zostanie zwrócona tylko do jednego, właściwego, inputu. Jednak jest to rozwiązanie słabe, bo wymusza określone nazewnictwo i refaktoring kodu, który został już wklepany - w serwisach i dao.

2. Tworzymy nową klasę, wrappującą beany,

```public class FormClass {
	private Payment payment;
	private Contact contact;
// gettery i settery
}```

i ustawiamy ją jako modelAttribute stojący za formą. Wtedy path, dla inputów ma wartość path="payment.name". 

1 użytkowników online, w tym zalogowanych: 0, gości: 1