JSR-303 @Valid 주석이 자식 개체 목록에 대해 작동하지 않습니다.


95

내 주요 수업은

public class UserAddressesForm {

    @NotEmpty
    private String firstName;

    @NotEmpty
    private String lastName;

    private List<AddressForm> addresses;

...
setters and getters 

public class AddressForm {

    @NotEmpty
    private String customName;
    @NotEmpty
    private String city;
    @NotEmpty
    private String streetAn;
    @NotEmpty
    private String streetHn;
    @NotEmpty
    private String addressCountry;
    @NotEmpty
    private String postCode;
...
setters and getters

컨트롤러

@RequestMapping(value = "/up", method = RequestMethod.POST)
    public String completeForm(@Valid @ModelAttribute("userAddressesForm") UserAddressesForm userAddressesForm,  
            BindingResult result, HttpServletRequest req)
...

JSP 페이지

<form:form commandName="userAddressesForm" action="registered">
    <table>

        <tr>
            <td class="formLabels"><form:label path="firstName">
                <spring:message code="label.name" />
            </form:label></td>
            <td><form:input path="firstName" /></td>
            <td><form:errors path="firstName" cssClass="error" /></td>
        </tr>
        <tr>
            <td class="formLabels"><form:label path="lastName">
                <spring:message code="label.surname" />
            </form:label></td>
            <td><form:input path="lastName" /></td>
            <td><form:errors path="lastName" cssClass="error" /></td>
        </tr>
    </table>

    <c:forEach items="${userAddressesForm.addresses}" varStatus="gridRow">  
        <div id="main_address" class="address_data_form">
            <fieldset>
                <legend><spring:message code="label.stepThreeMainAddressInfo" /></legend>
                <a href="#" class="deleteItem"></a>
                <table>
                    <tr>            
                        <td class="formLabels">
                            <spring:message code="label.address.custom.name" />
                        </td>
                        <td>
                            <spring:bind path="addresses[${gridRow.index}].customName">
                                <input type="input" name="<c:out value="${status.expression}"/>"
                                    id="<c:out value="${status.expression}"/>"
                                    value="<c:out value="${status.value}"/>" />
                                    <form:errors path="${status.expression}"/>
                            </spring:bind>
                        </td>   
                    </tr>               
                    <tr>            
                        <td class="formLabels">
                            <spring:message code="label.streetAnStreetHn" />
                        </td>
                        <td>
                            <spring:bind path="addresses[${gridRow.index}].streetAn">
                                <input type="input" name="<c:out value="${status.expression}"/>"
                                    id="<c:out value="${status.expression}"/>"
                                    value="<c:out value="${status.value}"/>" />
                            </spring:bind>
                            <spring:bind path="addresses[${gridRow.index}].streetHn">
                            <input type="input" name="<c:out value="${status.expression}"/>"
                                id="<c:out value="${status.expression}"/>"
                                value="<c:out value="${status.value}"/>" >
                            <form:errors path="addresses[${gridRow.index}].streetHn"/>
                            </spring:bind>

                        </td>
                    </tr>
                    <tr>                        
                        <td class="formLabels">
                            <spring:message code="label.postCode" />
                        </td>
                        <td>
                            <spring:bind path="addresses[${gridRow.index}].postCode">
                                <input type="input" name="<c:out value="${status.expression}"/>"
                                    id="<c:out value="${status.expression}"/>"
                                    value="<c:out value="${status.value}"/>" />
                            </spring:bind>
                        </td>                   
                    </tr>
                    <tr>                
                        <td class="formLabels">
                            <spring:message code="label.city" />
                        </td>
                        <td>
                            <spring:bind path="addresses[${gridRow.index}].city">
                                <input type="input" name="<c:out value="${status.expression}"/>"
                                    id="<c:out value="${status.expression}"/>"
                                    value="<c:out value="${status.value}"/>" />
                                <form:errors path="addresses[${gridRow.index}].city" cssClass="error" />
                            </spring:bind>
                        </td>
                    </tr>       
                </table>    
            </fieldset>
        </div>
    </c:forEach>

개체 필드가 ​​AddressForm의 유효성을 검사하지 않는 이유는 무엇입니까?

도와주세요.

답변:


164

addresses멤버 UserAddressesForm@Valid주석 으로 장식해야합니다 . JSR 303 : Bean Validation 의 섹션 3.1.3 및 3.5.1을 참조하십시오 . Annotated method를 사용하여 JSR 303 Bean Validation을 활성화하는 표준 방법이 있습니까? 라는 질문에 대한 답변에서 설명했듯이 JSR 303에 따른 @Valid주석 의 실제 사용입니다 .

예제 코드 편집 : Hibernate Validator- Object Graph . (자동차 탑승객 목록)

Hibernate Validator 6 참조 문서 에서 편집 :

6 이전 버전에서 Hibernate Validator는 컨테이너 요소의 하위 집합에 대해 계단식 유효성 검사를 지원했으며 컨테이너 수준에서 구현되었습니다 (예 :에 @Valid private List<Person>대한 계단식 유효성 검사를 활성화 하는 데 사용 Person).

이것은 여전히 ​​지원되지만 권장되지는 않습니다. @Valid더 표현력이있는 대신 컨테이너 요소 수준 주석을 사용하세요 .

예:

public class Car {

        private List<@NotNull @Valid Person> passengers = new ArrayList<Person>();

        private Map<@Valid Part, List<@Valid Manufacturer>> partManufacturers = new HashMap<>();

       //...
   }

또한 Bean Validation 2.0 / Jakarta Bean Validation 의 새로운 기능을 참조하십시오 .


그룹화는 어떻습니까? 그룹 A가 검증 된 경우에만 주소가 검증되기를 원합니다. @Valid그룹을 무시합니다.
Akshay

1
@Akshay @Valid주석은 하위 수준에서 작동합니다. @GroupSequence 를 사용하여 유효성 검사 순서를 지정할 수 있다고 생각합니다 .
Ritesh

내 자세한 질문 stackoverflow.com/q/41457404/1534925 . 내 경우에는 시퀀스가 ​​작동한다고 생각하지 마십시오.
Akshay

27

@Ritesh 답변에 추가하면 @Valid제약 조건은 Bean Validator가 적용된 속성의 유형을 조사하고 거기에서 발견 된 모든 제약 조건을 확인하도록 지시합니다. 질문에 대한 코드로 대답하면 유효성 검사기 @Validaddresses속성에 대한 제약 조건을 볼 때 다음과 같이 AddressForm클래스 를 탐색하고 JSR 303내부에있는 모든 제약 조건의 유효성을 검사 합니다.

public class UserAddressesForm {

    @NotEmpty
    private String firstName;

    @NotEmpty
    private String lastName;

    @Valid
    private List<AddressForm> addresses;

...
setters and getters 

public class AddressForm {

    @NotEmpty
    private String customName;
    @NotEmpty
    private String city;
    @NotEmpty
    private String streetAn;
    @NotEmpty
    private String streetHn;
    @NotEmpty
    private String addressCountry;
    @NotEmpty
    private String postCode;
...
setters and getters

1
그룹화는 어떻습니까? 그룹 A가 검증 된 경우에만 주소가 검증되기를 원합니다. @Valid 그룹을 무시
하기 Akshay

나는 당신의 대답을 읽지 않았지만 단지 setters and getters내 문제 를 해결했습니다.
Shubham Khandare

8

UserAddressesForm 클래스에서 다음 행을 추가하십시오.

@Valid
private List<AddressForm> addresses;

4

작업 솔루션.

public class UserAddressesForm {

    @NotEmpty(message="firstName is required")
    private String firstName;

    @NotEmpty(message="lastNameis required")
    private String lastName;

    @NotNull(message="addresses attributes are required")
    @Valid
    private List<AddressForm> addresses;

...
setters and getters 

public class AddressForm {

    @NotEmpty(message="customNameis required")
    private String customName;
    @NotEmpty
    private String city;
    @NotEmpty
    private String streetAn;
    @NotEmpty
    private String streetHn;
    @NotEmpty
    private String addressCountry;
    @NotEmpty
    private String postCode;
...
setters and getters
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.