使用Hibernate进行Spring MVC和bean验证

时间:2014-01-27 20:23:27

标签: hibernate spring-mvc bean-validation

解释起来有点复杂,但请耐心等待。我有一个带有几个属性的bean Student,我注释了所有需要使用Hibernate注释验证的属性。当我想搜索学生时,我只需要一些带注释/验证的属性,但是对所有这些属性进行了验证,这些都不允许搜索正确执行。

这是学生豆:

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "STUDENT_ID", unique = true, nullable = false)
    private Integer studentId;

    @NotNull(message = "First name is null!")
    @NotBlank(message = "Please enter first name!")
    @Column(name = "FIRST_NAME", nullable = false, length = 50)
    private String firstName;

    @NotNull(message = "Last name is null!")
    @NotBlank(message = "Please enter last name!")
    @Column(name = "LAST_NAME", nullable = false, length = 50)
    private String lastName;

    @NotNull(message = "MK is null!")
    @NotBlank(message = "Please enter MK!")
    @Column(name = "MK", nullable = false, length = 2)
    private String mk;

    @NotNull(message = "Roll number is null!")
    @NotBlank(message = "Please enter roll number!")
    @Column(name = "ROLL_NUMBER", nullable = false, length = 4)
    private String rollNumber;

    @NotNull(message = "Roll year is null!")
    @NotBlank(message = "Please enter roll year!")
    @Column(name = "ROLL_YEAR", nullable = false, length = 4)
    private String rollYear;

    //not populated by user, no validation needed
    @Column(name = "INDEX_NUMBER", unique = true, nullable = false, length = 20)
private String indexNumber;

    //for populating MK field only, no validation needed
    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch=FetchType.EAGER)
    @JoinColumn(name = "PROGRAM_FK", nullable = false)
    private Program program;

这是控制器:

    @RequestMapping(value="/search", method = RequestMethod.POST)
    public String postSearchStudent(
            @RequestParam(value = "mk") String programId,
            @RequestParam(value = "rollNumber") String rollNumber,
            @RequestParam(value = "rollYear") String rollYear,
            @RequestParam(value = "indexNumber") String indexNumber,
            @Valid @ModelAttribute("searchStudentAttribute") Student student,
            BindingResult result,
            Model model) {

        logger.debug("Received request to search for a student");

        if (result.hasErrors()) {
            model.addAttribute("programList", programService.getAll());
            return "searchStudent";
        }
        else {
            student = studentService.search(indexNumber);
            // if student isn't in the db show add student page, else redirect to student page
            if (student == null) {
                student = new Student();
                student.setRollNumber(rollNumber);
                student.setRollYear(rollYear);
                student.setIndexNumber(indexNumber);
                Program program = programService.get(programId);
                student.setProgram(program);
                model.addAttribute("student", student);
                return "addStudent";
            }
            else {
                Integer studentId = student.getStudentId();
                model.addAttribute("studentId", studentId);
                return "redirect:/essays/main/student/{studentId}";
            }
        }
    }

这是观点:

<c:url var="searchUrl" value="/essays/main/student/search" />
<form:form modelAttribute="searchStudentAttribute" method="POST" action="${searchUrl}">
 <form:errors path="*" cssClass="errorblock" element="div" />

 <form:label path="program">Select program (MK):</form:label>
 <form:select path="program" id="programSelect" size="8">
    <form:options items="${programList}" itemValue="programId" itemLabel="programDescription" />            
 </form:select>

 <form:label path="mk">MK</form:label>
 <form:input path="mk" id="mkInput" size="2" maxlength="2"/>
 <form:errors path="mk" cssClass="error"/>

 <form:label path="rollNumber">Roll number</form:label>
 <form:input path="rollNumber" id="rollNumberInput" size="4"/>
 <form:errors path="rollNumber" cssClass="error"/>

 <form:label path="rollYear">Roll year</form:label>
 <form:input path="rollYear" id="rollYearInput" size="4" maxlength="4"/>
 <form:errors path="rollYear" cssClass="error"/>

 <form:label path="indexNumber" />
 <form:hidden path="indexNumber" id="indexNumberInput" />

 <input type="submit" value="Submit" onclick="makeIndexNumber();"/>
</form:form>

如您所见,学生的名字和姓氏与搜索无关,因为搜索是由使用javaScript组合成一个的其他几个属性完成的。但是我需要稍后验证名字和姓氏,比如说,添加新学生,所以我不能只删除注释而根本不验证那些字段。有人可以告诉我,我应该制作一个单独的bean进行验证,仅用于搜索学生,还是有其他适当的解决方案?

让我更加明确:

enter image description here

当我提交所有字段为空的表单时,我会收到这些错误。如何在不删除注释进行验证的情况下告诉它不要考虑名字和姓氏属性?

2 个答案:

答案 0 :(得分:2)

这是使用验证组的一个好方案。要了解验证组,请查看此链接 -

Validation Groups

标准@Valid注释仍然不支持组。因此,您可以使用Spring特定的@Validated注释以及验证组。

@Validated

答案 1 :(得分:0)

@NotNull注释表明您无法为注释变量分配null - 值。我无法在您提供的代码中的任何地方看到您这样做,但这就是我认为发生的事情:

当您将对象传递给Spring MVC时,它会创建它自己的对象表示,然后该对象可用于生成的jsp - 类。当您提交表单时,转换会以另一种方式进行,它会使用它的set - 方法重新创建原始对象。因此,当您创建新的Student时,firstNamelastName变量将为null,这很好。然后将其传递给Spring MVC,同时将两个变量值转换为null。但是,在提交表单后,Spring MVC会尝试翻译,setFirstName(null),然后就会出现问题。

有几种方法可以解决这种情况。

  1. 简单的一个,只需将firstNamelastName变量设置为&#34;&#34; (空字符串),然后将其传递给Spring MVC。然后它永远不会尝试为它们分配null - 值,它将是空字符串。
  2. 优雅的一个,创建一个新类StudentSearchCommand或类似的东西,它将作为搜索对话框的后备对象。这个类应该具有执行搜索所需的字段,因此Student所有字符都有,除了名字和姓氏,但没有验证,JPA-annotation(只是普通的Ol&#39; Java对象(PO​​JO))。实例化此类并将其发送到Spring MVC,并在提交表单时,从中选择值并填充Student - 对象。通过这种方式,您可以超越Spring MVC对您的域类的要求(例如&#34;必须有一个setter&#34;),并按照您想要的方式保留它们并打算使用它们。