hibernatebean验证问题

hibernatebean验证问题,hibernate,validation,spring-mvc,bean-validation,hibernate-validator,Hibernate,Validation,Spring Mvc,Bean Validation,Hibernate Validator,我正在使用Spring3.1和HibernateValidator4.2。我发现hibernate验证被调用了两次: 当我使用如下方法时,控制器级别的一个: @RequestMapping(method = RequestMethod.POST) public String onSubmit(@Valid User user, BindingResult result) {....} 以及第二次将实体作为以下内容的一部分进行持久化: org.hibernate.cfg.beanval

我正在使用Spring3.1和HibernateValidator4.2。我发现hibernate验证被调用了两次: 当我使用如下方法时,控制器级别的一个:

 @RequestMapping(method = RequestMethod.POST)
    public String onSubmit(@Valid User user, BindingResult result) {....}
以及第二次将实体作为以下内容的一部分进行持久化:

org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(..)
org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreUpdate(..)
org.hibernate.action.EntityUpdateAction.preUpdate(..)
我认为在控制器级别有效并显示错误消息的错误页面更有意义。无论如何,在流中进行两次相同的验证是不好的。 我在hibernate文档中发现,可以通过在hibernate配置中将
hibernate.validator.autoregister\u侦听器设置为false来关闭它,但不建议这样做


那么,推荐的验证方法是什么?另外,在我的特殊情况下,第二次验证会带来麻烦,因为我有一个字段“
confirmPassword
”,当用户提交表单时,该字段是验证所必需的,但在表中不是必需的,所以每当我必须保存时,更新用户,我必须不必要地设置
confirmPassword
字段,以使验证通过。

验证不是一件容易的事情,尽管外观如此

前端验证针对填写表单的用户,可以从一个视图更改为另一个视图(例如,不同的消息)。视图中必填字段的消息应该是“字段是必需的!”,当实体被持久化时,后端的消息应该是:“字段不能为null”

后端验证应该总是在保存类时发生,考虑事实上持久的实体可以在不从视图中传递的情况下保存(例如从从WebService接收数据的批处理或从队列到另一个源……)。p> 如果在实体级别放置验证注释,则在该类上强制执行契约,该契约独立于该类是否已在视图中使用的事实

ConfirmPassword是一个视图字段,因此我认为不应该作为字段出现在实体中(例如,我用JSF开发了一个类似的案例,我将ConfirmPassword放在与该视图相关的ManagedBean中,而不是实体中,实体只包含密码字段)


因此,我认为总结两次“相同”的验证是正确的。

尽管表面看来验证并不容易

前端验证针对填写表单的用户,可以从一个视图更改为另一个视图(例如,不同的消息)。视图中必填字段的消息应该是“字段是必需的!”,当实体被持久化时,后端的消息应该是:“字段不能为null”

后端验证应该总是在保存类时发生,考虑事实上持久的实体可以在不从视图中传递的情况下保存(例如从从WebService接收数据的批处理或从队列到另一个源……)。p> 如果在实体级别放置验证注释,则在该类上强制执行契约,该契约独立于该类是否已在视图中使用的事实

ConfirmPassword是一个视图字段,因此我认为不应该作为字段出现在实体中(例如,我用JSF开发了一个类似的案例,我将ConfirmPassword放在与该视图相关的ManagedBean中,而不是实体中,实体只包含密码字段)


因此,总结一下,我认为两次“相同”的验证是正确的。

一切都取决于用例,并在一定程度上取决于个人喜好@obe6建议使用两种不同的bean,这在某些情况下可能有用,但在其他情况下则没有。关于confirmPassword字段,您可以在实体中将其标记为@Transient,这样该值就不会被持久化


我个人可能会通过@Valid禁用Spring验证,因为它不是标准的。另一方面,JPA生命周期事件上的Bean验证是无效的。我想这是另一个口味的问题。不过,两者都有似乎是不必要的。

一切都取决于用例,并在一定程度上取决于个人喜好@obe6建议使用两种不同的bean,这在某些情况下可能有用,但在其他情况下则没有。关于confirmPassword字段,您可以在实体中将其标记为@Transient,这样该值就不会被持久化


我个人可能会通过@Valid禁用Spring验证,因为它不是标准的。另一方面,JPA生命周期事件上的Bean验证是无效的。我想这是另一个口味的问题。但这两个都有似乎是不必要的。

所以您建议我应该有两个pojo bean,一个用于视图验证的userForm,另一个用于保存到数据库的user。我在两者上都有验证注释。很常见的例子是,一个bean同时用于jsp表单和保存到数据库,通过保存代码将字段从一个bean复制到另一个bean。在我的经验中,不总是(总是)有一个单独的类用于视图和数据库,考虑到视图中很少有来自许多持久性实体的当前字段(我称之为域模型上的‘视图’),而且(如在您的情况下使用确认密码)有些字段没有意义持久化。在我的例子中,有一个bean(userForm)保存持久类bean(有时指更持久的bean):在我的例子中,confirmPassword/confirmEmail位于“表单bean”中,password/email字段位于“实体”(持久bean)中。嗯,是的,您所说的对于使用两类对象VOs和DTO来说非常有意义。我觉得代码中会有很多语句,比如:“user.setEmail(userForm.getEmail())”,这看起来不太好。就我所记得的,即使Spring Roo生成的代码使用相同的类来查看和DB。UHM…我试图澄清得更好,我不太喜欢DTO(许多书认为它是反模式…例如EJB 3在运行中)。DTO的成本通常是不合理的。请注意,在我的示例中,我并不依赖丑陋的“复制代码”,因为我将confirmPassword保存在单独的类中(managedbean:viewBean),并且“password”字段仅在pers中声明