这一点在网络上仍然很混乱并且不清楚,因此这是我解决问题的方法。此解决方案可能不是最优化的解决方案,但在 创建和更新 主实体时可以使用。
理论对于应该动态管理的一对多关系,请使用a
List
代替aSet
。将初始化
List
为AutoPopulatingList
。这是一个懒惰列表,允许动态 添加 元素。添加一个属性
remove
的int
,以你的子实体。这将充当布尔标志的一部分,并且在动态 删除 元素时将很有用。在发布形式,坚持只有具有该标志的元素
remove
上0
(即false
)。
一个完整的例子:一个雇主有很多雇员,一个雇员有一个雇主。
实体:Employer.java
@Entity@Table(name = "employer")public class Employer private Integer id; private String firstname; private String lastname; private String company; private List<Employee> employees; // one-to-many }
Employee.java
控制器:@Entity@Table(name = "employee")public class Employee { private Integer id; @Transient // means "not a DB field" private Integer remove; // boolean flag private String firstname; private String lastname; private Employer employer; // many-to-one }
EmployerController.java
视图:@Controller@RequestMapping("employer")public class EmployerController { // Manage dynamically added or removed employees private List<Employee> manageEmployees(Employer employer) { // Store the employees which shouldn't be persisted List<Employee> employees2remove = new ArrayList<Employee>(); if (employer.getEmployees() != null) { for (Iterator<Employee> i = employer.getEmployees().iterator(); i.hasNext();) { Employee employee = i.next(); // If the remove flag is true, remove the employee from the list if (employee.getRemove() == 1) { employees2remove.add(employee); i.remove(); // Otherwise, perform the links } else { employee.setEmployer(employer); } } } return employees2remove; } // -- Creating a new employer ---------- @RequestMapping(value = "create", method = RequestMethod.GET) public String create(@ModelAttribute Employer employer, Model model) { // Should init the AutoPopulatingList return create(employer, model, true); } private String create(Employer employer, Model model, boolean init) { if (init) { // Init the AutoPopulatingList employer.setEmployees(new AutoPopulatingList<Employee>(Employee.class)); } model.addAttribute("type", "create"); return "employer/edit"; } @RequestMapping(value = "create", method = RequestMethod.POST) public String create(@Valid @ModelAttribute Employer employer, BindingResult bindingResult, Model model) { if (bindingResult.hasErrors()) { // Should not re-init the AutoPopulatingList return create(employer, model, false); } // Call the private method manageEmployees(employer); // Persist the employer employerService.save(employer); return "redirect:employer/show/" + employer.getId(); } // -- Updating an existing employer ---------- @RequestMapping(value = "update/{pk}", method = RequestMethod.GET) public String update(@PathVariable Integer pk, @ModelAttribute Employer employer, Model model) { // Add your own getEmployerById(pk) model.addAttribute("type", "update"); return "employer/edit"; } @RequestMapping(value = "update/{pk}", method = RequestMethod.POST) public String update(@PathVariable Integer pk, @Valid @ModelAttribute Employer employer, BindingResult bindingResult, Model model) { // Add your own getEmployerById(pk) if (bindingResult.hasErrors()) { return update(pk, employer, model); } List<Employee> employees2remove = manageEmployees(employer); // First, save the employer employerService.update(employer); // Then, delete the previously linked employees which should be now removed for (Employee employee : employees2remove) { if (employee.getId() != null) { employeeService.delete(employee); } } return "redirect:employer/show/" + employer.getId(); } // -- Show an existing employer ---------- @RequestMapping(value = "show/{pk}", method = RequestMethod.GET) public String show(@PathVariable Integer pk, @ModelAttribute Employer employer) { // Add your own getEmployerById(pk) return "employer/show"; }}
employer/edit.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%><%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE HTML><html><head> <title>Edit</title> <style type="text/css">.hidden {display: none;}</style> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script> <script type="text/javascript"> $(function() { // Start indexing at the size of the current list var index = ${fn:length(employer.employees)}; // Add a new Employee $("#add").off("click").on("click", function() { $(this).before(function() { var html = '<div id="employees' + index + '.wrapper" >'; html += '<input type="text" id="employees' + index + '.firstname" name="employees[' + index + '].firstname" />'; html += '<input type="text" id="employees' + index + '.lastname" name="employees[' + index + '].lastname" />'; html += '<input type="hidden" id="employees' + index + '.remove" name="employees[' + index + '].remove" value="0" />'; html += '<a href="#" data-index="' + index + '">remove</a>'; html += "</div>"; return html; }); $("#employees" + index + "\.wrapper").show(); index++; return false; }); // Remove an Employee $("a.employees\.remove").off("click").on("click", function() { var index2remove = $(this).data("index"); $("#employees" + index2remove + "\.wrapper").hide(); $("#employees" + index2remove + "\.remove").val("1"); return false; }); }); </script></head><body> <c:choose> <c:when test="${type eq 'create'}"><c:set var="actionUrl" value="employer/create" /></c:when> <c:otherwise><c:set var="actionUrl" value="employer/update/${employer.id}" /></c:otherwise> </c:choose> <form:form action="${actionUrl}" modelAttribute="employer" method="POST" name="employer"> <form:hidden path="id" /> <table> <tr> <td><form:label path="firstname">Firstname</form:label></td> <td><form:input path="firstname" /><form:errors path="firstname" /></td> </tr> <tr> <td><form:label path="lastname">Lastname</form:label></td> <td><form:input path="lastname" /><form:errors path="lastname" /></td> </tr> <tr> <td><form:label path="company">company</form:label></td> <td><form:input path="company" /><form:errors path="company" /></td> </tr> <tr> <td>Employees</td> <td> <c:forEach items="${employer.employees}" varStatus="loop"> <!-- Add a wrapping div --> <c:choose> <c:when test="${employer.employees[loop.index].remove eq 1}"> <div id="employees${loop.index}.wrapper" > </c:when> <c:otherwise> <div id="employees${loop.index}.wrapper"> </c:otherwise> </c:choose> <!-- Generate the fields --> <form:input path="employees[${loop.index}].firstname" /> <form:input path="employees[${loop.index}].lastname" /> <!-- Add the remove flag --> <c:choose> <c:when test="${employees[loop.index].remove eq 1}"><c:set var="hiddenValue" value="1" /></c:when> <c:otherwise><c:set var="hiddenValue" value="0" /></c:otherwise> </c:choose> <form:hidden path="employees[${loop.index}].remove" value="${hiddenValue}" /> <!-- Add a link to remove the Employee --> <a href="#" data-index="${loop.index}">remove</a> </div> </c:forEach> <button id="add" type="button">add</button> </td> </tr> </table> <button type="submit">OK</button> </form:form></body></html>
希望能有所帮助
:)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)