Bean検証における@NotNull、@NotEmpty、および@NotBlankの制約の違い

Bean検証における@ NotNull、@ NotEmpty、および@NotBlank制約の違い

1. 概要

Bean Validationis a standard validation specification that allows us to easily validate domain objects by using a set of constraints declared in the form of annotations

全体として、Hibernate ValidatorなどのBean Validation実装の使用はかなり簡単ですが、これらの制約のいくつかの実装方法に関して、微妙でありながら関連性のあるいくつかの違いを調べる価値があります。

このチュートリアルでは、we’ll spot the differences between the @NotNull, @NotEmpty, and @NotBlank constraints

2. Mavenの依存関係

作業環境をすばやくセットアップし、@NotNull@NotEmpty、および@NotBlank制約の動作をテストするには、最初に必要なMaven依存関係を追加する必要があります。

この場合、ドメインオブジェクトの検証には、Bean検証リファレンス実装であるHibernate Validatorを使用します。

pom.xmlファイルの関連セクションは次のとおりです。


    
        org.hibernate
        hibernate-validator
        6.0.13.Final
    
    
        org.glassfish
        javax.el
        3.0.0
     

単体テストではJUnitAssertJを使用するので、hibernate-validatorGlassFish’s EL implementationjunit、および%()の最新バージョンを確認してください。 t5)s MavenCentralで。

3. @NotNull制約

先に進むと、ナイーブなUserNotNullドメインクラスとconstrainnameフィールドに@NotNullアノテーションを付けて実装しましょう。

public class UserNotNull {

    @NotNull(message = "Name may not be null")
    private String name;

    // standard constructors / getters / toString
}

ここで、@NotNullが実際に内部でどのように機能するかを確認する必要があります

そのために、クラスの簡単な単体テストを作成し、そのいくつかのインスタンスを検証しましょう。

@BeforeClass
public static void setupValidatorInstance() {
    validator = Validation.buildDefaultValidatorFactory().getValidator();
}

@Test
public void whenNotNullName_thenNoConstraintViolations() {
    UserNotNull user = new UserNotNull("John");
    Set> violations = validator.validate(user);

    assertThat(violations.size()).isEqualTo(0);
}

@Test
public void whenNullName_thenOneConstraintViolation() {
    UserNotNull user = new UserNotNull(null);
    Set> violations = validator.validate(user);

    assertThat(violations.size()).isEqualTo(1);
}

@Test
public void whenEmptyName_thenNoConstraintViolations() {
    UserNotNull user = new UserNotNull("");
    Set> violations = validator.validate(user);

    assertThat(violations.size()).isEqualTo(0);
}

予想どおり、@NotNull制約は、制約されたフィールドにnull値を許可しません。 それでも、フィールドは空にすることができます。

これをよりよく理解するために、@NotNull制約が使用するNotNullValidator classisValid()メソッドを見てみましょう。 メソッドの実装は本当に簡単です。

public boolean isValid(Object object) {
    return object != null;
}

上に示したように、a field (e.g. CharSequence, Collection, Map, or Array) constrained with @NotNull must be not null. An empty value, however, is perfectly legal

4. @NotEmpty制約

それでは、サンプルのUserNotEmptyクラスを実装し、@NotEmpty制約を使用してみましょう。

public class UserNotEmpty {

    @NotEmpty(message = "Name may not be empty")
    private String name;

    // standard constructors / getters / toString
}

クラスを配置したら、nameフィールドに異なる値を割り当ててテストしてみましょう。

@Test
public void whenNotEmptyName_thenNoConstraintViolations() {
    UserNotEmpty user = new UserNotEmpty("John");
    Set> violations = validator.validate(user);

    assertThat(violations.size()).isEqualTo(0);
}

@Test
public void whenEmptyName_thenOneConstraintViolation() {
    UserNotEmpty user = new UserNotEmpty("");
    Set> violations = validator.validate(user);

    assertThat(violations.size()).isEqualTo(1);
}

@Test
public void whenNullName_thenOneConstraintViolation() {
    UserNotEmpty user = new UserNotEmpty(null);
    Set> violations = validator.validate(user);

    assertThat(violations.size()).isEqualTo(1);
}

@NotEmptyアノテーションは、@NotNullクラスのisValid()実装を利用し、さらに、提供されたオブジェクトのサイズ/長さをチェックします(もちろん、これは検証されるオブジェクトのタイプによって異なります) )がゼロより大きい。

一言で言えば、this means that a field (e.g. CharSequence, Collection, Map, or Array) constrained with @NotEmpty must be not null and its size/length must be greater than zero

さらに、@Size.と組み合わせて@NotEmptyアノテーションを使用すると、さらに制限を厳しくすることができます。

その際、オブジェクトの最小サイズと最大サイズの値が指定された最小/最大範囲内にあることも強制します。

@NotEmpty(message = "Name may not be empty")
@Size(min = 2, max = 32, message = "Name must be between 2 and 32 characters long")
private String name;

5. @NotBlank制約

同様に、@NotBlankアノテーションを使用してクラスフィールドを制約できます。

public class UserNotBlank {

    @NotBlank(message = "Name may not be blank")
    private String name;

    // standard constructors / getters / toString

}

同じ方針に沿って、@NotBlank制約がどのように機能するかを理解するための単体テストを実装できます。

@Test
public void whenNotBlankName_thenNoConstraintViolations() {
    UserNotBlank user = new UserNotBlank("John");
    Set> violations = validator.validate(user);

    assertThat(violations.size()).isEqualTo(0);
}

@Test
public void whenBlankName_thenOneConstraintViolation() {
    UserNotBlank user = new UserNotBlank(" ");
    Set> violations = validator.validate(user);

    assertThat(violations.size()).isEqualTo(1);
}

@Test
public void whenEmptyName_thenOneConstraintViolation() {
    UserNotBlank user = new UserNotBlank("");
    Set> violations = validator.validate(user);

    assertThat(violations.size()).isEqualTo(1);
}

@Test
public void whenNullName_thenOneConstraintViolation() {
    UserNotBlank user = new UserNotBlank(null);
    Set> violations = validator.validate(user);

    assertThat(violations.size()).isEqualTo(1);
}

@NotBlankアノテーションは、NotBlankValidatorクラスを使用します。このクラスは、文字シーケンスのトリミングされた長さが空でないことを確認します。

public boolean isValid(
  CharSequence charSequence,
  ConstraintValidatorContext constraintValidatorContext)
    if (charSequence == null ) {
        return true;
    }
    return charSequence.toString().trim().length() > 0;
}

面白いことに、メソッドはnull値に対してtrueを返します。 したがって、@NotBlankはnull値を許可すると思うかもしれませんが、実際には許可していません。

@NotNullクラスのisValid()メソッドは、@NotBlankクラスのisValid()の後に呼び出されるため、null値は禁止されています。

簡単に言うと、a String field constrained with @NotBlank must be not null and the trimmed length must be greater than zeroです。

6. 並べて比較

これまで、@NotNull@NotEmpty、および@NotBlank制約がクラスフィールドで個別にどのように機能するかについて詳しく見てきました。

制約の機能を俯瞰して、それらの違いを簡単に見つけることができるように、簡単に並べて比較してみましょう。

  • @NotNull:制約付きCharSequenceCollectionMap,、またはArrayは、nullでない限り有効ですが、空にすることもできます

  • @NotEmpty:制約付きCharSequenceCollectionMap,、またはArrayは、nullでなく、サイズ/長さがゼロより大きい限り有効です。

  • @NotBlank:制約付きStringは、nullでなく、トリミングされた長さがゼロより大きい限り有効です。

7. 結論

この記事では、Bean Validationに実装されているNotNull@NotEmpty、および@NotBlank制約を確認し、それらの類似点と相違点を強調しました。

いつものように、この記事に示されているすべてのコードサンプルは利用可能なover on GitHubです。