Spring MVC+PostgreSQL+Hibernate环境下表单提交客户端错误解决
Let's break down what's causing your client-side request failure (likely a 400 Bad Request) and fix it step by step:
Root Causes of the Issue
- Invalid use of
pathattribute: You're using thepathattribute on plain HTML tags (<select>,<input>), but this attribute only works with Spring's form tags (<form:form>,<form:select>,<form:input>). Without Spring's form tag support, yourpathvalues are ignored, so Spring can't properly bind form data to yourDistrictmodel. - Conflicting parameter binding: Your
addDistrictmethod uses both@ModelAttribute("district")and a separate@RequestParam("division"). This creates ambiguity for Spring when mapping form data, leading to failed binding. - Potential relative path issue: The
redirect:districtlistmight resolve to an incorrect URL depending on the current page's path (e.g.,/createdistrict/districtlistinstead of/districtlist).
Step-by-Step Fixes
1. Update JSP to Use Spring Form Tags
First, add the Spring form taglib to your JSP, then replace plain HTML form elements with Spring's form tags. This enables proper use of the path attribute for model binding:
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <form:form method="POST" action="/adddistrict" modelAttribute="district"> <table class="create-table table table-hover"> <tr> <td> Division </td> <td> <form:select path="division.id" id="division"> <form:option value="" label="Select a Division"/> <c:forEach items="${allDivision}" var="divisionEntry"> <form:option value="${divisionEntry.key}" label="${divisionEntry.value}"/> </c:forEach> </form:select> </td> </tr> <tr> <td> Name </td> <td> <form:input path="name" id="name"/> </td> </tr> </table> <div class="button-set text-right"> <button type="submit" class="btn site-btn filled-btn" id="savebutton">save</button> <a href="/districtlist" class="btn site-btn filled-btn">cancel</a> <a href="/createdistrict" class="btn site-btn filled-btn">reset</a> </div> </form:form>
2. Simplify the Controller Method
Remove the redundant @RequestParam("division") parameter. Spring will automatically bind the selected division ID to district.division.id using the path attribute from the form:
@PostMapping("/adddistrict") public String addDistrict(@ModelAttribute("district") District district, Model model) { this.districtService.adddistrict(district); return "redirect:/districtlist"; // Use absolute path to avoid URL resolution issues }
3. Adjust the Service Layer
Update your adddistrict service method to fetch the actual Division entity from the database using the ID bound to district.division.id, then associate it with the District before saving:
public void adddistrict(District district) { // Fetch the Division entity using the ID from the form Integer divisionId = district.getDivision().getId(); Division division = divisionRepository.findById(divisionId) .orElseThrow(() -> new IllegalArgumentException("Invalid Division ID: " + divisionId)); // Associate the Division with the District district.setDivision(division); // Save the District to the database districtRepository.save(district); }
Additional Troubleshooting Tips
- Check browser dev tools: Open F12 > Network tab to inspect the request parameters and response status code. A 400 status confirms binding issues.
- Enable Spring debug logs: Add debug logging for
org.springframework.webto see detailed parameter binding errors, which will tell you exactly which field is failing to bind. - Verify path mappings: Ensure your
redirect:/districtlistpoints to the correct endpoint (match the@RequestMappingof your district list controller).
内容的提问来源于stack exchange,提问作者OUN Saif

