1. 概要

Bean Validation は、アノテーションの形式で宣言された一連の制約を使用して、ドメインオブジェクトを簡単に検証できるようにする標準の検証仕様です。

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

このチュートリアルでは、 @ NotNull、@ NotEmpty、および@NotBlank制約の違いについて説明します。

2. Mavenの依存関係

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

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

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

<dependencies> 
    <dependency> 
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>6.0.13.Final</version>
    </dependency> 
    <dependency> 
        <groupId>org.glassfish</groupId>
        <artifactId>javax.el</artifactId>
        <version>3.0.0</version>
     </dependency>
</dependencies>

ユニットテストではJUnitAssertJを使用するため、 hibernate-validator GlassFishのEL実装[ Maven Centralの junit 、およびassertj-core

3. @NotNull制約

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

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<ConstraintViolation<UserNotNull>> violations = validator.validate(user);
 
    assertThat(violations.size()).isEqualTo(0);
}
    
@Test
public void whenNullName_thenOneConstraintViolation() {
    UserNotNull user = new UserNotNull(null);
    Set<ConstraintViolation<UserNotNull>> violations = validator.validate(user);
 
    assertThat(violations.size()).isEqualTo(1);
}
    
@Test
public void whenEmptyName_thenNoConstraintViolations() {
    UserNotNull user = new UserNotNull("");
    Set<ConstraintViolation<UserNotNull>> violations = validator.validate(user);
 
    assertThat(violations.size()).isEqualTo(0);
}

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

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

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

上に示したように、 フィールド(例: @NotNullで制約されたCharSequence、Collection、Map、またはArray)はnullであってはなりません。 ただし、空の値は完全に合法です

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<ConstraintViolation<UserNotEmpty>> violations = validator.validate(user);
 
    assertThat(violations.size()).isEqualTo(0);
}
    
@Test
public void whenEmptyName_thenOneConstraintViolation() {
    UserNotEmpty user = new UserNotEmpty("");
    Set<ConstraintViolation<UserNotEmpty>> violations = validator.validate(user);
 
    assertThat(violations.size()).isEqualTo(1);
}
    
@Test
public void whenNullName_thenOneConstraintViolation() {
    UserNotEmpty user = new UserNotEmpty(null);
    Set<ConstraintViolation<UserNotEmpty>> violations = validator.validate(user);
 
    assertThat(violations.size()).isEqualTo(1);
}

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

手短に、 これは、フィールド(例: @NotEmptyで制約されたCharSequence、Collection、Map、またはArray)はnullであってはならず、そのサイズ/長さはゼロより大きくなければなりません

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

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

@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<ConstraintViolation<UserNotBlank>> violations = validator.validate(user);
 
    assertThat(violations.size()).isEqualTo(0);
}
    
@Test
public void whenBlankName_thenOneConstraintViolation() {
    UserNotBlank user = new UserNotBlank(" ");
    Set<ConstraintViolation<UserNotBlank>> violations = validator.validate(user);
 
    assertThat(violations.size()).isEqualTo(1);
}
    
@Test
public void whenEmptyName_thenOneConstraintViolation() {
    UserNotBlank user = new UserNotBlank("");
    Set<ConstraintViolation<UserNotBlank>> violations = validator.validate(user);
 
    assertThat(violations.size()).isEqualTo(1);
}
    
@Test
public void whenNullName_thenOneConstraintViolation() {
    UserNotBlank user = new UserNotBlank(null);
    Set<ConstraintViolation<UserNotBlank>> 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値を禁止します。

簡単に言うと、 @NotBlankで制約された文字列フィールドはnullであってはならず、トリミングされた長さはゼロより大きくなければなりません

6. 並べて比較

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

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

  • @NotNull:制約付き CharSequence Collection Map、、または Array は、そうでない限り有効です。 nullですが、空にすることができます。
  • @NotEmpty:制約付き CharSequence Collection Map、、または Array は、そうでない限り有効です。 nullであり、そのサイズ/長さがゼロより大きい。
  • @NotBlank:制約付きの String は、nullでなく、トリミングされた長さがゼロより大きい限り有効です。

7. 結論

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

いつものように、この記事に示されているすべてのコードサンプルは、GitHubから入手できます。