【问题标题】:What is point of constraint validation @Null?什么是约束验证@Null?
【发布时间】:2017-06-21 18:09:03
【问题描述】:

我正在检查javax.validation 包中的list of available constraints,我注意到有一个注释@Null 强制该字段为空。

如果我已经知道它应该为空,我不明白将它添加到我的字段有什么意义。

例如看这个类:

public class MyClass{

    @NotNull
    private String myString1;

    @Null
    private String myString2;

    // getter setters...
}

@NotNull 完全有道理。我不希望 myString1 为空。但是@Null 使myString2 无用。拥有一个应该始终为空的字段有什么意义。

【问题讨论】:

  • 它不应该总是为空。在验证对象时它应该为 null。想象一个属于类的字段,但不能由用户提交,因为它是稍后计算并添加到对象中的。
  • 对于分组验证约束和定义方法的结果也很有用。
  • @JBNizet,我了解您的用例,但我认为该字段不应该在用户输入类中,因为用户与它无关。如果我想向其中添加额外的字段,我应该将用户输入类转换为不同的类。如果我继续使用同一个类,我将无法再验证它,这违背了这些约束验证的目的。
  • 我并不是说这样做是个好主意。我只是说它发生了,并且 Null 在这种情况下很有用。
  • @JBNizet 是对的。这是针对不同情况的简单约束。例如具有ID 字段的实体在保存到数据库之前应该是null。或者您有应该保存到您的系统中的对象但某些字段,例如某些 paymentID 应该由 3rd 方服务检索和更新,在这种情况下,当您要保存此对象时,您验证此字段 @Null,然后一些其他线程(服务)将读取此对象并另外更新该字段。所以一切都取决于你的用例。

标签: jakarta-ee constraints bean-validation


【解决方案1】:

您可能希望将@Null 与“验证组”结合使用,以仅在某些情况下验证空约束。

Good explanation and example on validation groups provided by Hibernate

您将验证组定义为简单接口

public interface FirstSave {}

然后在约束中使用它

public class MyClass {

    @Null(groups = FirstSave.class)
    private LocalDate lastUpdate;
}

那么如果lastUpdate 不是 null,调用validator.validate(myClassInstance) 不会产生约束冲突(使用默认组),但调用validator.validate(myClassInstance, FirstSave.class)会.

您还可以就如何使用注释提供您自己的实现,即我已经看到验证方法使用@Null 进行注释,其中该方法返回的null 表示一切正常。在后台可能有自定义实现如果带注释的方法返回非空结果该怎么办,但我没有深入研究代码......

【讨论】:

    【解决方案2】:

    @Null 是一个非常重要的注解。它不是没用的。让我展示一个常见的用例。比如说,有一个带有 Id 自动生成的 DAO(实体)对象。

    如果您为 DTO 和 DAO 使用单独的类,@GetMapping 将返回 DTO 列表而不会出现问题。另一方面,@PostMapping 添加新元素要求输入 DTO 不得包含 Id 字段,即使存在,它也必须为 null 或未定义。 这样的输入在与 DTO 对象相互转换时,要求 Id 必须为空。 为此,@Null 是唯一的选择

    @PutMapping 要求 id 不能为空,因此当我们希望单个对象发生更新时,id 字段需要 @NotNull

    @DeleteMapping 只需要整数 Id ,仅当我们想要删除具有已知 Id 的对象时。

    还有其他复杂的情况,通常不处理但有意义

    @GetMapping 可用于任何提供的字段,但如果提供了除 Id 以外的任何字段,则 Id 必须为空。如果提供了 ID,则所有其他必须为空。

    还有一个复杂的@PutMapping要求, 其中为更新提供了部分信息,并且预期剩余字段是较旧的值。此处更新非空字段。

    另一个注解@DeleteMapping用于删除或移除。如果计算为空白,则可以使用@Null 约束来实现。

    通常的 CRUD 操作过于简单,但不适合实际期望的用例。

    所有这些需求组合都可以分组列出。 并且可以通过groups属性提供约束,可以根据需要应用单独的标记接口@Validated

    【讨论】:

      【解决方案3】:

      引用this 文档,这里是空注释的要求。

      乍一看,在按合同设计的脉络中对 API 规范使用空注释仅意味着所有 API 方法的签名都应该被完全注释,即除了像 int 这样的原始类型之外,每个参数和每个方法返回类型都应该是标记为@NonNull 或@Nullable。因为这意味着要插入很多空注释,所以很高兴知道在设计良好的代码(尤其是 API 方法)中,@NonNull 比 @Nullable 更频繁。因此,可以通过在包级别使用@NonNullByDefault 注释将@NonNull 声明为默认值来减少注释的数量。

      然而,话虽如此,是的,你是对的,@Null 没有多大意义,在设计良好的代码中,@NotNull 更重要,也更频繁。 @Null 或 @Nullable 的存在只是为了表示此处需要空值,并有助于防止调用者和被调用者对空值进行冗余检查。希望这会有所帮助。

      【讨论】:

      • 感谢您的回答。提供的文档是关于 @NonNull@Nullable 但这个问题是关于 javax.validation 注释 @Null 以及它在验证中的可能用法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-10
      • 2015-06-27
      • 1970-01-01
      • 1970-01-01
      • 2010-09-22
      • 2015-01-11
      相关资源
      最近更新 更多