【问题标题】:Weird problem with Spring MVC, Bean Validation using @Valid and HibernateSpring MVC 的奇怪问题,使用 @Valid 和 Hibernate 的 Bean 验证
【发布时间】:2011-05-19 05:56:17
【问题描述】:

我有一个应用程序在 50 个域类中使用 bean 验证。在 Spring MVC 控制器中使用 @Valid 已经工作了几个月,没有任何问题。

现在突然之间,我在 Hibernate 中让许多字段“懒惰”以提高性能。我不得不处理各种奇怪的问题,从 equals() 方法不再工作,到会话中的对象因为数据未加载而崩溃。

我现在遇到了一个非常奇怪的问题,我 am 将数据加载到 Spring MVC 表单上的会话属性中,视图会正确呈现它,但是当传递给 @Valid 时,它会报告即使数据 100% 有效,所有字段都有错误。

public class EducationFacility extends DomainObject {

    /* Members */
    @NotEmpty(message = "{educationFacility.name.notEmpty}")
    private String name;

    @Valid
    private Address address = new Address();

    @Pattern(message = "{educationFacility.phoneNumber.valid}",
        regexp = "(\\()?(\\d){3}(\\))?(\\s|-)(\\d){3}(\\s|-)(\\d){4}")
    private String phoneNumber = "";
    ...
}

这是休眠的定义:

<class name="jobprep.domain.educationfacility.EducationFacility" table="education_facility">
    <id name="id" column="education_facility_id" type="long">
        <generator class="native" />
    </id>
    <property name="name" column="name"/>
    <component name="address" class="jobprep.domain.educationfacility.Address">
        <property name="address" column="address"/>
        <property name="postalCode" column="postal_code"/>
        <many-to-one name="province" class="jobprep.domain.educationfacility.Province" column="province_id"  />
    </component>
    <property name="phoneNumber" column="phone_number"/>
    <property name="isEnabled" column="is_enabled"/>
    <property name="homepageViewable" column="homepage_viewable" />
    <property name="coursesCreated" />
    <many-to-one name="admin" class="jobprep.domain.user.Admin" column="admin_id" />
    <many-to-one name="director" class="jobprep.domain.educationfacility.Director"
                 column="director_id" cascade="all" />
    <bag name="teachers" inverse="true" cascade="all-delete-orphan" order-by="username asc">
        <key column="education_facility_id" />
        <one-to-many class="jobprep.domain.teacher.Teacher" />
    </bag>
    <bag name="students" inverse="true" cascade="all-delete-orphan" order-by="username asc">
        <key column="student_education_facility_id" />
        <one-to-many class="jobprep.domain.student.Student"/>
    </bag>
    <bag name="ipRestrictions" inverse="true" cascade="all-delete-orphan">
        <key column="education_facility_id" />
        <one-to-many class="jobprep.domain.educationfacility.IpRestriction" />
    </bag>
    <bag name="allowedModules" table="education_facility_to_module"
         inverse="false" lazy="true">
        <key column="education_facility_id" />
        <many-to-many class="jobprep.domain.module.Module" column="module_id"/>
    </bag>
</class>

这是控制器定义:

@Controller
@RequestMapping("/myEducationFacility")
@SessionAttributes("educationFacility")
@PreAuthorize("hasRole('ROLE_DIRECTOR')")
public class MyEducationFacilityController extends ControllerSupport {
    ....
}

这是 MVC 的保存方法:

    @RequestMapping(value = "/save", method = RequestMethod.POST)
    public String save(@Valid EducationFacility educationFacility, BindingResult result, SessionStatus status) {
        if(result.hasErrors()) {
            return view("index");
        } else {
            adminService.saveEducationFacility(educationFacility);
            status.setComplete();

            return redirect("?complete=true");
        }
    }

当 Spring 调用 save() 时,Spring is added to binding 结果中的错误如下。这些是完全错误的:

{org.springframework.validation.BindingResult.educationFacility=org.springframework.validation.BeanPropertyBindingResult: 4 errors
    Field error in object 'educationFacility' on field 'phoneNumber': rejected value [(519) 254-3678]; codes [Pattern.educationFacility.phoneNumber,Pattern.phoneNumber,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [educationFacility.phoneNumber,phoneNumber]; arguments []; default message [phoneNumber],[Ljavax.validation.constraints.Pattern$Flag;@29895454,(\()?(\d){3}(\))?(\s|-)(\d){3}(\s|-)(\d){4}]; default message [Must be of the form: ###-###-####]
    Field error in object 'educationFacility' on field 'address.address': rejected value [Windsor]; codes [NotEmpty.educationFacility.address.address,NotEmpty.address.address,NotEmpty.address,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [educationFacility.address.address,address.address]; arguments []; default message [address.address]]; default message [Address may not be empty]
    Field error in object 'educationFacility' on field 'name': rejected value [Catholic School Board]; codes [NotEmpty.educationFacility.name,NotEmpty.name,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [educationFacility.name,name]; arguments []; default message [name]]; default message [Name may not be empty]
    Field error in object 'educationFacility' on field 'address.postalCode': rejected value [N9a 2a5]; codes [Pattern.educationFacility.address.postalCode,Pattern.address.postalCode,Pattern.postalCode,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [educationFacility.address.postalCode,address.postalCode]; arguments []; default message [address.postalCode],[Ljavax.validation.constraints.Pattern$Flag;@29895454,[a-zA-Z]\d[a-zA-Z](\s|-)\d[a-zA-Z]\d]; default message [Postal Code must be of the format: a#a-#a#], educationFacility=class jobprep.domain.educationfacility.EducationFacility{id=3}}

帮助?

【问题讨论】:

    标签: hibernate spring validation spring-mvc javabeans


    【解决方案1】:

    只是一个猜测,但尝试在 getter 而不是字段上设置约束注释。由于某些延迟加载魔法,字段状态可能与 getter 返回的值不匹配。

    【讨论】:

    • 我会试试看的。这很奇怪,因为在其他两种形式上,@Valid 确实有效(教育设施注册,以及当管理员向系统添加/编辑新教育设施时)。它仅在导演编辑自己的教育设施时报告错误错误。是的,我确保调用服务层并将其从数据库中加载出来——而不是使用当前用户会话中的那个。这种东西背后令人沮丧,让我想完全抛弃hibernate。
    • 我只是把它搞砸了,让 director.educationFacility lazy="false"。那是唯一有效的方法。愚蠢的冬眠。我有时讨厌它。既然你是唯一一个打扰回复的人,我会把答案归功于你,这样你就可以获得积分。
    【解决方案2】:

    问题确实是约束放置。想想看,延迟加载是通过代理和方法拦截来工作的。这仅在您将约束放在实体的 getter 上时才有效。代理必须通过方法调用来访问。如果您像在放置约束时一样直接访问这些字段,则 Validator 正在验证代理本身。另见https://forum.hibernate.org/viewtopic.php?f=9&t=1005515http://opensource.atlassian.com/projects/hibernate/browse/HV-348

    【讨论】:

      猜你喜欢
      • 2015-05-01
      • 2011-06-29
      • 2015-01-06
      • 2012-09-15
      • 2021-12-09
      • 2016-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多