Spring MVC + Hibernate:数据验证策略

     2023-02-26     245

关键词:

【中文标题】Spring MVC + Hibernate:数据验证策略【英文标题】:Spring MVC + Hibernate: data validation strategies 【发布时间】:2012-09-21 12:49:04 【问题描述】:

我们都知道,Spring MVC 通常与 Hibernate Validator 和 JSR-303 集成得很好。但是正如有人所说,Hibernate Validator 只是 Bean Validation 的东西,这意味着更复杂的验证应该被推送到数据层。此类验证的示例:业务密钥唯一性、记录内依赖性(这通常指向数据库设计问题,但我们都生活在一个不完美的世界中)。即使是像字符串字段长度这样的简单验证也可能由一些 DB 值驱动,这使得 Hibernate Validator 无法使用。

所以我的问题是,Spring、Hibernate 或 JSR 是否提供了一些东西来执行如此复杂的验证?在基于 Spring 和 Hibernate 的标准 Controller-Service-Repository 设置中是否有一些已建立 模式或技术来执行此类验证?

更新:让我说得更具体一些。例如,有一个表单向控制器的save 方法发送AJAX 保存请求。如果出现一些验证错误——无论是简单的还是“复杂的”——我们应该用一些 json 指示有问题的字段和相关错误返回浏览器。对于简单的错误,我可以从BindingResult 中提取字段(如果有)和错误消息。对于“复杂”错误,您会建议什么基础设施(可能是特定的,而不是临时例外?)?使用异常处理程序对我来说似乎不是一个好主意,因为在 save 方法和 @ExceptionHandler 之间分离单个验证过程会使事情变得复杂。目前我使用一些临时异常(例如,ValidationException):

public @ResponseBody Result save(@Valid Entity entity, BindingResult errors) 
    Result r = new Result();
    if (errors.hasErrors()) 
        r.setStatus(Result.VALIDATION_ERROR);     
        // ...   
     else 
        try 
            dao.save(entity);
            r.setStatus(Result.SUCCESS);
         except (ValidationException e) 
            r.setStatus(Result.VALIDATION_ERROR);
            r.setText(e.getMessage());
        
    
    return r;

你能提供一些更优化的方法吗?

【问题讨论】:

【参考方案1】:

是的,Exception throwing 的 Java 模式已经确立了良好的旧模式。 Spring MVC 集成的很好(代码示例可以直接跳到我回答的第二部分)。

您所说的“复杂验证”实际上是例外:业务密钥唯一性错误、低层或数据库错误等。


提醒:Spring MVC 中的验证是什么?

验证应该发生在表示层上。它基本上是关于验证提交的表单字段。

我们可以将它们分为两种:

1) 轻度验证(使用 JSR-303/Hibernate 验证):检查提交的字段是否具有给定的 @Size/@Length,它是 @NotNull@NotEmpty /@NotBlank,检查它是否具有@Email 格式等。

2) 重度验证或复杂验证更多的是关于字段验证的特定情况,例如跨字段验证:

示例 1:表单有 fieldAfieldBfieldC。每个字段可以单独为空,但至少其中一个不能为空。 示例 2:如果 userAge 字段的值小于 18,则responsibleUser 字段不能为空且responsibleUser 的年龄必须大于 21。

可以使用Spring Validator implementations 或custom annotations/constraints 来实现这些验证。

现在我明白了,有了所有这些验证工具,再加上 Spring 完全没有侵入性并且可以让你做任何你想做的事情(无论好坏),人们可能会想使用“验证锤”来任何与错误处理模糊相关的内容。 它会起作用:仅通过验证,您可以检查验证器/注释中的所有可能问题(并且几乎不会在较低层抛出任何异常)。这很糟糕,因为你祈祷你考虑过所有的情况。您不会利用 Java 异常来简化逻辑并通过忘记检查是否有错误来减少出错的机会。

所以在 Spring MVC 世界中,不应该将验证(即 UI 验证)误认为是低层 异常,例如有 Service 异常或 DB 异常(关键唯一性等)。


如何在Spring MVC中轻松处理异常?

有些人认为“天哪,所以在我的控制器中,我必须一一检查所有可能的已检查异常,并为每个异常考虑一个消息错误?没办法!”。我是那些人的其中一个。 :-)

在大多数情况下,只需使用一些通用的检查异常类,所有异常都会扩展。然后只需在 Spring MVC 控制器中使用 @ExceptionHandler 和通用错误消息进行处理。

代码示例:

public class MyAppTechnicalException extends Exception  ... 

@Controller
public class MyController 

    ...

    @RequestMapping(...)
    public void createMyObject(...) throws MyAppTechnicalException 
        ...
        someServiceThanCanThrowMyAppTechnicalException.create(...);
        ...
    

    ...

    @ExceptionHandler(MyAppTechnicalException.class)
    public String handleMyAppTechnicalException(MyAppTechnicalException e, Model model) 

        // Compute your generic error message/code with e.
        // Or just use a generic error/code, in which case you can remove e from the parameters
        String genericErrorMessage = "Some technical exception has occured blah blah blah" ;

        // There are many other ways to pass an error to the view, but you get the idea
        model.addAttribute("myErrors", genericErrorMessage);

        return "myView";
    


简单、快速、简单、干净!

当您需要为某些特定异常显示错误消息时,或者由于无法修改的旧系统设计不佳而无法提供通用***异常时,只需添加其他 @ExceptionHandlers。 另一个技巧:对于不那么混乱的代码,您可以使用

处理多个异常
@ExceptionHandler(MyException1.class, MyException2.class, ...)
public String yourMethod(Exception e, Model model) 
    ...


底线:何时使用验证?什么时候使用异常?

来自 UI 的错误 = 验证 = 验证工具(JSR-303 注释、自定义注释、Spring 验证器) 来自较低层的错误 = 异常

当我说“来自 UI 的错误”时,我的意思是“用户在他的表单中输入了错误”。

参考资料:

Passing errors back to the view from the service layer Very informative blog post about bean validation

【讨论】:

杰罗姆,感谢您抽出宝贵时间。请查看更新的问题,我添加了一些细节。您能对此发表意见吗? 我已阅读您的更新,它不会改变我回答的基本内容。使用@ExceptionHandler,您不会分离验证过程,因为异常处理不是验证。在一个好的应用程序中,我认为你应该处理验证和异常:它们在技术上是两个不同的东西。所以没有分离,事情也不复杂。现在,如果您碰巧在验证处理和异常处理中进行了相同的处理,我建议您编写一个方法,例如“processError(...)”,这两个部分都会调用。希望这会有所帮助,我想我不能说更多 不过,如果它们以相同的结尾(向用户显示验证消息)和来自相同的开头(用户输入无效数据),我无法理解它们在“技术上是两个不同的东西” )?假设我没有一个方法,但是有 两个 方法可以抛出这个 ValidationException (一个是保存,另一个 - 删除,删除可能由于非系统错误而失败)并且它们都返回不同的结构JSON。我如何辨别在@ExceptionHandler 中返回哪个视图? 它们是两个不同的东西,因为它们不是验证:数据库错误,因为基础已满,数据库中不存在要更新的元素,您的控制器所依赖的 Web 服务离线或有问题,服务无法创建文件,因为文件夹上的权限已被更改,以及我现在没有想到的任何其他异常:对于大多数情况,您想警告用户“发生了一些意外错误” .至于您的示例,您可以使用 SaveException 和 DeleteException 来实现差异,您可以使用两个不同的 @ExceptionHandler 来处理它们。 简单示例——业务密钥唯一性检查,不是“base is full”之类的系统错误,但与@NotNullcheck still大致相同,它需要复杂像 DB 一样处理。你会把这张支票放在哪里?如果在@ExceptionHandler 中,那么我无法理解为什么将其与BindingResult 支票分开。开发人员希望找到组合(或至少链接)在一起的所有验证步骤。如果控制器很大,将它们放入单独的方法中需要额外的脑力劳动(例如,“验证消息来自哪里?!不是来自 BindingResult!”)。

在spring mvc中选择spring hibernate中的查询

】在springmvc中选择springhibernate中的查询【英文标题】:Selectqueryinspringhibernateinspringmvc【发布时间】:2014-07-1109:36:27【问题描述】:嗨,我正在编写一个springmvc,使用mysql数据库、hibernate注释和jsp的员工应用程序。该数据库包含一... 查看详情

使用 Spring Boot + Hibernate + MySql 运行 MVC 应用程序

】使用SpringBoot+Hibernate+MySql运行MVC应用程序【英文标题】:RunningaMVCappusingSpringBoot+Hibernate+MySql【发布时间】:2014-08-2207:00:11【问题描述】:我是Spring环境的新手。我试图使用SpringBoot和Hibernate作为ORM和MYSQL作为数据库来开发一个基... 查看详情

Spring Mvc Hibernate Encoding/多行导入sql

】SpringMvcHibernateEncoding/多行导入sql【英文标题】:SpringMvcHibernateEncoding/Multi-lineimportsql【发布时间】:2015-10-0516:10:11【问题描述】:我正在研究SpringMVC,在项目启动时,我已将database设置为导入默认sql使用休眠配置hibernate.hbm2ddl.imp... 查看详情

Hibernate - Spring Security - Spring MVC 版本

】Hibernate-SpringSecurity-SpringMVC版本【英文标题】:Hibernate-SpringSecurity-SpringMVCVersions【发布时间】:2018-04-0514:34:09【问题描述】:我正在尝试使用SpringSecurity、SpringMVC和Hibernate实现一个Web应用程序。经过对互联网的一些研究,我面临... 查看详情

spring 4 mvc + Hibernate + Annotations 配置堆内存问题

】spring4mvc+Hibernate+Annotations配置堆内存问题【英文标题】:spring4mvc+Hibernate+AnnotationsconfigurationHeapmemoryissue【发布时间】:2017-06-2806:42:37【问题描述】:环境细节是。IntellijIDESpring4Hibernatewithsimpleschemaof30tablesElasticsearchclientMys 查看详情

当数据正确显示时,为啥我在这个 Spring MVC Web 应用程序中得到一个 Hibernate LazyInitializationException?

...正确显示时,为啥我在这个SpringMVCWeb应用程序中得到一个HibernateLazyInitializationException?【英文标题】:WhyamIgettingaHibernateLazyInitializationExceptioninthisSpringMVCwebapplicationwhenthedatadisplayscorrectly?当数据正确显示时,为什么我在这个SpringMVC... 查看详情

如何提高 Spring MVC - Hibernate - JSP - AngularJS v1.6 的性能? [关闭]

】如何提高SpringMVC-Hibernate-JSP-AngularJSv1.6的性能?[关闭]【英文标题】:HowtoincreaseperformanceinSpringMVC-Hibernate-JSP-AngularJSv1.6?[closed]【发布时间】:2018-05-0603:45:48【问题描述】:给我一​​些想法/建议/解决方案,以更快地检索数据和... 查看详情

我们如何使用hibernate作为orm单独的数据库和模式来构建一个spring mvc多租户应用程序

】我们如何使用hibernate作为orm单独的数据库和模式来构建一个springmvc多租户应用程序【英文标题】:howcanwebuildaspringmvcmultitenantapplicationusinghibernateasormseparatedatabaseandschema【发布时间】:2019-12-3008:17:51【问题描述】:你从springio转... 查看详情

从 Migrate 迁移到 Spring MVC 4 + Hibernate5

】从Migrate迁移到SpringMVC4+Hibernate5【英文标题】:MigratingfromMigratetoSpringMVC4+Hibernate5【发布时间】:2017-08-0322:39:51【问题描述】:我正在将应用程序从Jersey1.18、Spring3、Hibernate3.6、Maven迁移到全新的架构:Spring4.3(通过SpringBoot)、Hi... 查看详情

Spring MVC + Hibernate 4 + Spring Security

】SpringMVC+Hibernate4+SpringSecurity【英文标题】:【发布时间】:2012-12-0504:06:23【问题描述】:从现在开始,我一直在努力完成所有这些工作,不知道该怎么办。我相信我在SO上浏览了关于该主题的每一篇文章,并浏览了数十个教程..... 查看详情

集成magnolia和spring mvc,hibernate

】集成magnolia和springmvc,hibernate【英文标题】:integratingmagnoliaandspringmvc,hibernate【发布时间】:2015-03-1814:02:50【问题描述】:我们正在使用开花插件将SpringMVC集成到Magnolia中。以下是我们集成的步骤。-创建bloom项目,然后添加一些... 查看详情

请解释spring MVC,hibernate和Spring security

】请解释springMVC,hibernate和Springsecurity【英文标题】:PleaseExplainspringMVC,hibernateandSpringsecurity【发布时间】:2017-01-0323:44:24【问题描述】:在很多指南的帮助下,我刚刚使用Spring安全性和休眠创建了我的第一个登录页面。我遇到的... 查看详情

带有 Spring、Spring MVC、Hibernate、JPA 的项目的 Maven 3 原型

】带有Spring、SpringMVC、Hibernate、JPA的项目的Maven3原型【英文标题】:Maven3ArchetypeforProjectWithSpring,SpringMVC,Hibernate,JPA【发布时间】:2013-01-1316:42:33【问题描述】:我正在尝试使用Maven3创建一个使用Spring3、SpringMVC、Hibernate4和JPA的项... 查看详情

Spring boot、mvc、hibernate 和 mysql 配置 - sessionFactory 错误

】Springboot、mvc、hibernate和mysql配置-sessionFactory错误【英文标题】:Springboot,mvc,hibernateandmysqlconfiguration-sessionFactoryerror【发布时间】:2017-02-1005:29:33【问题描述】:我是春季靴子的新手。我想用mysql、hibernate、jpa和jsp配置springboot。... 查看详情

Spring 框架 MVC - Hibernate 异常是 java.lang.NoSuchMethodError

】Spring框架MVC-Hibernate异常是java.lang.NoSuchMethodError【英文标题】:SpringframeworkMVC-Hibernateexceptionisjava.lang.NoSuchMethodError【发布时间】:2016-02-1506:41:00【问题描述】:我发布这个问题是关于我在JavaSpringFrameworkMVC-Hibernate中的一个项目。... 查看详情

确保 AUTHENTICATED 用户被授权访问资源的最佳实践 - Spring mvc、Spring Security、Hibernate

...TED用户被授权访问资源的最佳实践-Springmvc、SpringSecurity、Hibernate【英文标题】:BestpracticetomakesureanAUTHENTICATEDuserisAUTHORISEDtoaccessaresource-Springmvc,SpringSecurity,Hibernate【发布时间】:2016-06-1808:52:10【问题描述】:我们有一个spring 查看详情

Spring MVC“org.hibernate.PropertyAccessException”中的休眠注释映射异常

】SpringMVC“org.hibernate.PropertyAccessException”中的休眠注释映射异常【英文标题】:HibernateAnnotationMappingExceptioninSpringMVC"org.hibernate.PropertyAccessException"【发布时间】:2015-01-2017:13:18【问题描述】:我是SpringMVC和Hibernate的新手。... 查看详情

Spring MVC + Hibernate DAO:无法连接 bean

】SpringMVC+HibernateDAO:无法连接bean【英文标题】:SpringMVC+HibernateDAOs:unabletowirebeans【发布时间】:2012-06-0120:49:28【问题描述】:我目前正在开发一个集成了Hibernate的SpringMVC项目。纯SpringMVC部分(DispatcherServlet+请求映射)工作正常... 查看详情