保持双向多对多关系列(加入表)

时间:2015-08-06 01:27:46

标签: java spring hibernate jsp jpa

我在用户提供相同数据后访问连接表相关数据时遇到问题。

以下是相关代码

ServiceCategory.java(模型类)

@Entity
@Table(name = "servicecategory")
public class ServiceCategory  extends BaseEntity {
/**
 * 
 */
private static final long serialVersionUID = 1L;

@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

//@Size(min = 3, max = 50)
@Column(name = "servicecatname", nullable = false)
private String serviceCatName;

//@Size(min = 3, max = 200)
@Column(name = "servicecatdescription", nullable = false)
private String serviceCatDescription;

//@Size(min = 3, max = 500)
@Column(name = "servicecatimagefilename", nullable = false)
private String serviceCatImageFileName;

@ManyToMany(targetEntity = Employee.class, cascade = { CascadeType.ALL })
@JoinTable(name = "servicecategory_employee", joinColumns = { @JoinColumn(name = "servicecatid") }, inverseJoinColumns = { @JoinColumn(name = "empid") })
private List<Employee> employees = new ArrayList<>();

@Transient
private MultipartFile serviceCatImage;

private Boolean deleted;

public String getServiceCatName() {
    return serviceCatName;
}

public void setServiceCatName(String serviceCatName) {
    this.serviceCatName = serviceCatName;
}

public String getServiceCatDescription() {
    return serviceCatDescription;
}

public void setServiceCatDescription(String serviceCatDescription) {
    this.serviceCatDescription = serviceCatDescription;
}

public String getServiceCatImageFileName() {
    return serviceCatImageFileName;
}

public void setServiceCatImageFileName(String serviceCatImageFileName) {
    this.serviceCatImageFileName = serviceCatImageFileName;
}

public List<Employee> getEmployees() {
    return employees;
}

public void setEmployees(List<Employee> employees) {
    this.employees = employees;
}

public Long getId() {
    return id;
}

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

public MultipartFile getServiceCatImage() {
    return serviceCatImage;
}

public void setServiceCatImage(MultipartFile serviceCatImage) {
    this.serviceCatImage = serviceCatImage;
}

public Boolean getDeleted() {
    return deleted;
}

public void setDeleted(Boolean deleted) {
    this.deleted = deleted;
}



}

Employee.java(模型类)

@Entity
@Table(name = "employee")
public class Employee extends BaseEntity {
/**
 * 
 */
private static final long serialVersionUID = 1L;

@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

//@Size(min = 3, max = 50)
@Column(name = "empfirstname", nullable = false)
private String empFirstName;

//@Size(min = 3, max = 50)
@Column(name = "emplastname", nullable = false)
private String empLastName;

//@Size(min = 3, max = 50)
@Column(name = "empdesignation", nullable = false)
private String empDesignation;

@OneToOne
@JoinColumn(name = "employeetypeid", nullable = true)
private EmployeeType employeeType;

//@Size(min = 3, max = 500)
@Column(name = "employeeImageFileName", nullable = false)
private String employeeImageFileName;

@ManyToMany(mappedBy="employees")
private List<ServiceCategory> serviceCategories = new ArrayList<>();

private Boolean deleted;

@Transient
private MultipartFile employeeImage;

public String getEmpFirstName() {
    return empFirstName;
}

public void setEmpFirstName(String empFirstName) {
    this.empFirstName = empFirstName;
}

public String getEmpLastName() {
    return empLastName;
}

public void setEmpLastName(String empLastName) {
    this.empLastName = empLastName;
}

public String getEmpDesignation() {
    return empDesignation;
}

public void setEmpDesignation(String empDesignation) {
    this.empDesignation = empDesignation;
}

public String getEmployeeImageFileName() {
    return employeeImageFileName;
}

public void setEmployeeImageFileName(String employeeImageFileName) {
    this.employeeImageFileName = employeeImageFileName;
}

public EmployeeType getEmployeeType() {
    return employeeType;
}

public void setEmployeeType(EmployeeType employeeType) {
    this.employeeType = employeeType;
}

public Long getId() {
    return id;
}

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

public List<ServiceCategory> getServiceCategories() {
    return serviceCategories;
}

public void setServiceCategories(List<ServiceCategory> serviceCategories) {
    this.serviceCategories = serviceCategories;
}

public Boolean getDeleted() {
    return deleted;
}

public void setDeleted(Boolean deleted) {
    this.deleted = deleted;
}

public MultipartFile getEmployeeImage() {
    return employeeImage;
}

public void setEmployeeImage(MultipartFile employeeImage) {
    this.employeeImage = employeeImage;
}


}

employeeadd.jsp

<section class="inner-banner">
<div class="container">
    <ol class="breadcrumb">
        <li><a href="#">Home</a></li>
        <li><a href="#">Employees</a></li>
        <li class="active">${ACTION} Employee</li>

    </ol>
</div>
</section>


<!-- form section-->
<section class="formSection">
    <div class="container">
        <h1 class="sectionHeading">${ACTION} Employee</h1>
        <div class="divider"></div>

        <form:form modelAttribute="employee" enctype="multipart/form-data" method="post">
            <div class="row">
                <div class="form-group col-lg-6 col-md-6 col-sm-12">
                    <form:label path="empFirstName">Employee First Name<em class="mandatory">*</em></form:label>
                    <div class="col-lg-10 col-md-12 col-sm-12">
                            <form:input path="empFirstName" cssClass="form-control"  />
                            <form:errors class="alert alert-danger" path="empFirstName" /> 
                </div>                  
                <div class="clearfix"></div>
            </div>

            <div class="form-group col-lg-6 col-md-6 col-sm-12">
                <form:label path="empLastName">Employee Last Name<em class="mandatory">*</em></form:label>
                <div class="col-lg-10 col-md-12 col-sm-12">
                        <form:input path="empLastName" cssClass="form-control"  />
                        <form:errors class="alert alert-danger" path="empLastName" />
                </div>                  
                <div class="clearfix"></div>
            </div>
        </div>

        <div class="row">
            <div class="form-group col-lg-6 col-md-6 col-sm-12">
                <form:label path="empDesignation">Employee Designation<em class="mandatory">*</em></form:label>
                <div class="col-lg-10 col-md-12 col-sm-12">
                        <form:input path="empDesignation" cssClass="form-control"  />
                        <form:errors class="alert alert-danger" path="empDesignation" /> 
                </div>                  
                <div class="clearfix"></div>
            </div>

            <div class="form-group col-lg-6 col-md-6 col-sm-12">
                <form:label path="employeeType">Employee Type<em class="mandatory">*</em></form:label>
                <div class="col-lg-10 col-md-12 col-sm-12">
                           <form:select path="employeeType.id"  class="selectpicker" multiple="false">
                                    <form:option value="0" label="   -- Please Select --" />
                                    <form:options items="${employeeTypeList}"  itemValue="id" itemLabel="employeeType"/>
                           </form:select>
                        <form:errors class="alert alert-danger" path="employeeType" />
                </div>                  
                <div class="clearfix"></div>
            </div>
        </div>

        <div class="row">
            <div class="form-group col-lg-6 col-md-6 col-sm-12">
                <form:label path="serviceCategories">Service Categories<em class="mandatory">*</em></form:label>
                <div class="col-lg-10 col-md-12 col-sm-12">                     
                           <form:select path="serviceCategories" class="selectpicker" multiple="true">
                                    <form:options items="${serviceCategoriesList}"  itemValue="id" itemLabel="serviceCatName"/>
                           </form:select>
                        <form:errors class="alert alert-danger" path="serviceCategories" />
                </div>                  
                <div class="clearfix"></div>
            </div>

            <div class="form-group col-lg-6 col-md-6 col-sm-12">
                <form:label path="employeeImage">Upload Employee Image<em class="mandatory">*</em></form:label>
                <div class="col-lg-10 col-md-12 col-sm-12">
                        <input name="employeeImage" type="file">
                        <form:errors class="alert alert-danger" path="employeeImage" />
                </div>                  
                <div class="clearfix"></div>
            </div>

            <c:if test="${ACTION == 'Edit'}">
               <form:hidden path="employeeImageFileName" />
            </c:if>
        </div>

        <div class="row">
            <div class="form-group col-lg-12 col-md-12 col-sm-12">
                <!-- <button type="submit" class=" orangebtn btn mtop20">
                    Submit <i class="fa fa-arrow-circle-right left"></i>
                </button> -->
                <form:button type="submit" class=" orangebtn btn mtop20">Submit <i class="fa fa-arrow-circle-right left"></i></form:button>
            </div>
        </div>          

    </form:form>

</div>

EmployeeController.java

    /* This method will be called on form submission, handling POST request for
     saving employee in database. It also validates the user input*/

    @RequestMapping(value = { "/add" }, method = RequestMethod.POST)
    public String saveEmployee(
            @Valid @ModelAttribute("employee") Employee employee,
            BindingResult result, ModelMap model, Map<String, Object> map,
            HttpServletRequest request) {

        boolean isError = false;

        logger.debug("Entered saveEmployee method");
        logger.debug("employee.getEmpFirstName() : "
                + employee.getEmpFirstName());
        logger.debug("employee.getEmpLastName() : "
                + employee.getEmpLastName());
        logger.debug("employee.getEmpDesignation() : "
                + employee.getEmpDesignation());
        logger.debug("employee.getEmployeeImage().getSize() : "
                + employee.getEmployeeImage().getSize());
        logger.debug("employee.getEmployeeType() : "
                + employee.getEmployeeType());
        logger.debug("employee.getServiceCategories() : "
                + employee.getServiceCategories());
        logger.debug("employee.getEmployeeType().getId() : "
                + employee.getEmployeeType().getId());
        logger.debug("employee.getServiceCategories().size() : "
                + employee.getServiceCategories().size());
}

当用户提交数据并选择服务类别时,日志中会打印以下内容

DEBUG   2015-08-06 11:07:36,679 [http--127.0.0.1-8080-3] com.abc.controller.EmployeeController  - Entered saveEmployee method
DEBUG   2015-08-06 11:07:36,679 [http--127.0.0.1-8080-3] com.abc.controller.EmployeeController  - employee.getEmpFirstName() : fsddf
DEBUG   2015-08-06 11:07:36,680 [http--127.0.0.1-8080-3] com.abc.controller.EmployeeController  - employee.getEmpLastName() : sdfsdsfdsdf
DEBUG   2015-08-06 11:07:36,680 [http--127.0.0.1-8080-3] com.abc.controller.EmployeeController  - employee.getEmpDesignation() : sdfsdfsd
DEBUG   2015-08-06 11:07:36,681 [http--127.0.0.1-8080-3] com.abc.controller.EmployeeController  - employee.getEmployeeImage().getSize() : 252227
DEBUG   2015-08-06 11:07:36,681 [http--127.0.0.1-8080-3] com.abc.controller.EmployeeController  - employee.getEmployeeType() : com.abc.model.EmployeeType@56261adf
DEBUG   2015-08-06 11:07:36,681 [http--127.0.0.1-8080-3] com.abc.controller.EmployeeController  - employee.getServiceCategories() : []
DEBUG   2015-08-06 11:07:36,682 [http--127.0.0.1-8080-3] com.abc.controller.EmployeeController  - employee.getEmployeeType().getId() : 1
DEBUG   2015-08-06 11:07:36,682 [http--127.0.0.1-8080-3] com.abc.controller.EmployeeController  - employee.getServiceCategories().size() : 0

即使我从视图中选择多个服务类别,我也不确定为什么employee.getServiceCategories()。size()为零。

提前感谢您的帮助。

更新

调试时我也尝试打印BindingResult结果的值,它显示我在日志中跟随

  DEBUG   2015-08-06 14:59:20,686 [http--127.0.0.1-8080-4] com.abc.controller.EmployeeController  - result : org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'employee' on field 'serviceCategories': rejected value [15,17]; codes [typeMismatch.employee.serviceCategories,typeMismatch.serviceCategories,typeMismatch.java.util.List,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [employee.serviceCategories,serviceCategories]; arguments []; default message [serviceCategories]]; default message [Failed to convert property value of type 'java.lang.String[]' to required type 'java.util.List' for property 'serviceCategories'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.abc.model.ServiceCategory] for property 'serviceCategories[0]': no matching editors or conversion strategy found]

1 个答案:

答案 0 :(得分:0)

发现问题所在。数据绑定存在问题,因为spring无法从serviceCategories变量获得list employee.serviceCategories的值。

我做了一些RnD(主要是参考Spring form binding how to do it ? Cannot convert value of type [java.lang.String] to required typehttp://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/validation.html#format-configuring-formatting-mvc)并在我的控制器中进行了以下更改

id= <?php echo $detail1[$i]['id'];?>