如何使用Spring MVC中的多对多注释将数据绑定到CheckBox

时间:2016-09-09 12:44:22

标签: java spring hibernate spring-mvc jpa

我想这样做;

我有一项工作要改进学习Spring,Hibernate和JPA的CRUD应用程序。所以我想做很多很多例子,但我要求别人这样做。

我想获得员工的驾驶执照和更新信息。我可以使用Spring forEach从Web数据库中获取员工的信息到CheckBox。如果员工拥有哪个驾驶执照,则必须检查关系CheckBoxes。我可以更新这些信息。

例如,员工已获得" A1"和" M"类。我可以获取并绑定数据。

我创建了"员工"," driving_licenses"的表格。 我创建了" employee_driving_licenses"对于商店员工的驾驶执照:

员工:

id          int
last_name   nvarchar(20)
first_name  nvarchar(10)

driving_licenses:

id      int 
code    nvarchar(5)

employee_driving_licenses:

employee_id         int
driving_license_id  int

我创建了表的模型类并添加了JPA注释。我有Employee和DrivingLicense实体Java类:

Employee.java

@Entity
@Table(name = "employees")
public class Employee {

    private int id;
    private String last_name;
    private String first_name;
    private java.util.Collection<DrivingLicense> driving_licenses = new HashSet<DrivingLicense>();

    @GeneratedValue(strategy = GenerationType.AUTO)
    @Id
    @Column
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @NotEmpty(message = "Please enter Last Name")
    @Column
    public String getLast_name() {
        return last_name;
    }

    public void setLast_name(String last_name) {
        this.last_name = last_name;
    }

    @NotEmpty(message = "Please enter First Name")
    @Column
    public String getFirst_name() {
        return first_name;
    }

    @ManyToMany(fetch = FetchType.EAGER, mappedBy = "employees")
    public java.util.Collection<DrivingLicense> getDriving_licenses() {
        return driving_licenses;
    }

    public void setDriving_licenses(
        java.util.Collection<DrivingLicense> driving_licenses) {this.driving_licenses = driving_licenses;
    }
}

DrivingLicense.java

@Entity
@Table(name = "driving_licenses")
public class DrivingLicense {

    private int id;
    private String code;
    private java.util.Collection<Employee> employees = new HashSet<Employee>();

    @Override
    public int hashCode() {
        return new Long(id).hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
                return false;
        }
        if (!(obj instanceof DrivingLicense)) {
                return false;
        }
        return this.id == ((DrivingLicense) obj).getId();
    }

    @GeneratedValue(strategy = GenerationType.AUTO)
    @Id
    @Column
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Column
    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    @ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
    @JoinTable(name = "employee_driving_licenses", joinColumns = { @JoinColumn(name = "driving_license_id", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "employee_id", nullable = false, updatable = false) })
    public java.util.Collection<Employee> getEmployees() {
        return employees;
    }

    public void setEmployees(java.util.Collection<Employee> employees) {
        this.employees = employees;
    }
}

我创建了应用程序DAO,服务,控制器和视图类/页面。

EmployeeController.java:

@RequestMapping(value = "index", method = RequestMethod.POST)
public String employee(@Valid @ModelAttribute("employee") Employee employee,
    BindingResult result, @RequestParam String action,
    java.util.Map<String, Object> map) {

    boolean isValid = true;
    if (result.hasErrors()) {
        isValid = false;
    }

    Employee employeeResult = new Employee();
    switch (action.toLowerCase()) {
        case "add":
            if (isValid) 
                employeeService.add(employee);
            employeeResult = employee;
        break;

        case "edit":
            if (isValid) 
               employeeService.edit(employee);
            employeeResult = employee;
        break;
    }
    map.put("drivingLicenseList", drivingLicenseService.findActiveDrivingLicense());
    map.put("employee", employeeResult);
    map.put("activeEmployeeList", employeeService.findActiveEmployees());
    return "employee";
}

employee.jsp:

<c:forEach var="drive_licenses" items="${drivingLicenseList}">
    <form:checkbox path="driving_licenses"
    value="${drive_licenses }" label="${drive_licenses.code }" />
</c:forEach>

当我想更新员工的驾驶执照时,我收到的错误代码如下:

{employee=com.ay.model.Employee@573cb29c, org.springframework.validation.BindingResult.employee=org.springframework.validation.BeanPropertyBindingResult:     1 errors
Field error in object 'employee' on field 'driving_licenses': rejected value      [com.ay.model.DrivingLicense@1,com.ay.model.DrivingLicense@7,com.ay.model.DrivingLicense@8,com.ay.model.Driving    License@9]; codes     [typeMismatch.employee.driving_licenses,typeMismatch.driving_licenses,typeMismatch.java.util.Collection,typeMis    match]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes     [employee.driving_licenses,driving_licenses]; arguments []; default message [driving_licenses]]; default     message [Failed to convert property value of type 'java.lang.String[]' to required type 'java.util.Collection'     for property 'driving_licenses'; nested exception is java.lang.IllegalStateException: Cannot convert value of     type [java.lang.String] to required type [com.ay.model.DrivingLicense] for property 'driving_licenses[0]': no     matching editors or conversion strategy found]}

如何获取Collection类型的值?请给我建议。

而且,如果我添加此代码

value="${drive_licenses }" 

在employee.jsp的网页上,我可以正常看到浏览器上的对象值。实际上我首先添加了这段代码

value="${drive_licenses.id }"

但CheckBox上未检查员工的驾驶执照,并且每个CheckBoxes值都为空。什么是真正的语法?

感谢您的支持。

1 个答案:

答案 0 :(得分:0)

这个部分太多了。大致是:

一个:创建一个包装器表单:

public class EmployeeForm{
    private Employee employee;

    //Driving licence needs a 'boolean' selected field
    //Mark as @Transient so not persisted
    //Otherwise create another wrapper/dto which has this boolean field
    //Spring MVC can only bind to indexed fields e.g. List
    private List<DrivingLicence> allAvailableLicences;

    public EmployeeForm(Employee employee, Collecion<DrivingLicence> licenes){
        //set instance vars
    }

    //getters
    //setters
}

两个:将以下内容添加到您的控制器:

//CALLED ON BOTH GET AND POST TO SET UP THE FORM
//FOR EDITING EXISTING EMPLOYEE REPLACE NEW EMPLOYEE WITH THE RELEVANT LOOKUP
@ModelAttribute("employeeForm")
public EmployeeForm getEmployeeForm(@RequestParam("employeeId", required = false) Long employeeId){
    return new EmployeeForm(new Employee(), drivingLicenseService.findActiveDrivingLicense());

}

<强>三

更改您的JSP表单以绑定到employeeForm:您可以使用嵌套属性,例如employee.name前面的路径属性。对于绑定许可证,您需要使用下面的索引表示法,即将列表中索引x处的许可证设置为选中。

<c:forEach var="licence" items="${employeeForm.allAvailableLicences}" varStatus="loop">
    <form:checkbox path="licence[${loop.index]}.selected" label="${licence.code }" />
</c:forEach>

四:

更新表单提交处理程序:

@RequestMapping(value = "index", method = RequestMethod.POST)
public String employee(@Valid @ModelAttribute("employeeForm") EmployeeForm employeeForm,
    BindingResult result, @RequestParam String action) {

    //validation etc

    Employee employee = employeeForm.getEmployee();

    for(DrivingLicence licence : employeeForm.getAllAvailableLicences()){
         //our indexed foem check box set the 'selected' field true
         //if selected add to the employee
    }

    //save updated employee

    return "nextPage";
}