Hibernate Validator固有の制約

1. 概要

このチュートリアルでは、Hibernate Validatorに組み込まれているが、Bean Validation仕様外のHibernate Validatorの制約を確認します。
Bean Validationの要約については、https://www.baeldung.com/javax-validation [Java Bean Validation Basics]の記事を参照してください。

2. Hibernate Validatorセットアップ

少なくとも、* https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.hibernate%22%20AND%20a%3A%22hibernate-validator%22 [ Hibernate Validator]を依存関係に追加:*
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.16.Final</version>
</dependency>
Hibernate Validatorはlink:/tag/hibernate/[Hibernate、ORM、他の多くの記事で説明しました。]に依存しないことに注意してください。
また、紹介するアノテーションの一部は、プロジェクトで特定のライブラリを使用する場合にのみ適用されます。 したがって、それらのそれぞれについて、必要な依存関係を示します。

*3. お金関連の価値の検証+

*

3.1. クレジットカード番号の検証

有効なクレジットカード番号は、https://en.wikipedia.org/wiki/Luhn_algorithm [Luhn's Algorithm]を使用して計算するチェックサムを満たす必要があります。 *ストリングがチェックサムを満たす場合、* @ CreditCardNumber_制約は成功します。*
  • _ @ CreditCardNumber_は、入力文字列に対してその他のチェックを実行しません。*特に、入力の長さはチェックしません。 したがって、小さなタイプミスのために無効な数値のみを検出できます。

    デフォルトでは、文字列に数字以外の文字が含まれている場合、制約は失敗しますが、無視するように指示できることに注意してください。
@CreditCardNumber(ignoreNonDigitCharacters = true)
private String lenientCreditCardNumber;
次に、スペースやダッシュなどの文字を含めることができます。
validations.setLenientCreditCardNumber("7992-7398-713");
constraintViolations = validator.validateProperty(validations, "lenientCreditCardNumber");
assertTrue(constraintViolations.isEmpty());

* 3.2。 金額の検証*

_ @ Currency_バリデーターは、特定の金額が指定された通貨であるかどうかを確認します。
@Currency("EUR")
private MonetaryAmount balance;
クラス_MonetaryAmount_はJava Moneyの一部です。 したがって、* _ @ Currency_はlink:/java-money-and-currency[Java Money実装が利用可能な場合]のみに適用されます。*
Java Moneyを正しく設定したら、制約を確認できます。
bean.setBalance(Money.of(new BigDecimal(100.0), Monetary.getCurrency("EUR")));
constraintViolations = validator.validateProperty(bean, "balance");
assertEquals(0, constraintViolations.size());

4. 範囲の検証

* 4.1。 数値および通貨の範囲*

Bean検証仕様では、数値フィールドに適用できるいくつかの制約を定義しています。 それらに加えて、Hibernate Validatorは、範囲を包括的に一致させる_ @ Min_と_ @ Max、_ **の組み合わせとして機能する便利な注釈_ @ Range_を提供します。
@Range(min = 0, max = 100)
private BigDecimal percent;
_ @ Min_や_ @ Max_と同様に、_ @ Range_はプリミティブ数型のフィールドとそのラッパーに適用できます。上記の_BigInteger_および_BigDecimal_、_String_表現、および最後に_MonetaryValue_フィールド。

* 4.2。 時間の長さ+

*
特定の時点を表す値の標準JSR 380アノテーションに加えて、Hibernate Validatorには__Duration__sの制約も含まれています。 link:/java-8-date-time-intro#period[Java Timeのof_Period_および_Duration_クラス]最初に必ずチェックアウトしてください。
そのため、*プロパティに最小期間と最大期間を強制できます:*
@DurationMin(days = 1, hours = 2)
@DurationMax(days = 2, hours = 1)
private Duration duration;
ここですべてを表示していなくても、注釈にはナノ秒から日までのすべての時間単位のパラメーターがあります。
デフォルトでは、*最小値と最大値が含まれます*。つまり、最小値または最大値とまったく同じ値が検証に合格することに注意してください。
境界値を無効にしたい場合は、代わりに_inclusive_プロパティをfalseに定義します。
@DurationMax(minutes = 30, inclusive = false)

5. 文字列の検証

* 5.1。 ストリングの長さ*

文字列が特定の長さであることを強制するために、わずかに異なる2つの制約を使用できます。
通常、文字列の長さ(_length_メソッドで測定するもの)が最小値と最大値の間にあることを確認する必要があります。 その場合、Stringプロパティまたはフィールドで_ @ Length_を使用します。
@Length(min = 1, max = 3)
private String someString;
*ただし、Unicodeの複雑さにより、文字の長さとコードポイントの長さが異なる場合があります。 後者を確認する場合は、_ @ CodePointLength:_ *を使用します
@CodePointLength(min = 1, max = 3)
private String someString;
たとえば、文字列「aa \ uD835 \ uDD0A」は4文字の長さですが、コードポイントは3つしか含まれていないため、最初の制約に失敗して2番目の制約を渡します。
また、両方の注釈で、最小値または最大値を省略できます。

* 5.2。 数字列のチェック+

*
文字列が有効なクレジットカード番号であることを確認する方法は既に説明しました。 ただし、Hibernate Validatorには、数字の文字列に対する他のいくつかの制約が含まれています。
最初に確認しているのは_ @ LuhnCheckです。これは_ @ CreditCardNumberの一般化バージョンです。
@LuhnCheck(startIndex = 0, endIndex = Integer.MAX_VALUE, checkDigitIndex = -1)
private String someString;
ここでは、パラメーターのデフォルト値を示したため、上記は単純な_ @ LuhnCheck_アノテーションと同等です。
しかし、見てわかるように、サブストリング(_startIndex_および_endIndex_)のチェックを実行し、どの数字がチェックサムディジットであるかを制約に伝えることができます。-1は、チェックされたサブストリングの最後の数字を意味します。
その他の興味深い制約には、https://www.activebarcode.com/codes/checkdigit/modulo10.html [モジュロ10チェック](_ @ Mod10Check_)およびhttps://www.activebarcode.com/codes/checkdigit/modulo11.htmlが含まれます。 [モジュロ11チェック](_ @ Mod11Check_)。これは通常、バーコードやISBNなどの他のコードに使用されます。
ただし、これらの特定のケースでは、Hibernate ValidatorがISBNコードを検証するための制約_ @ ISBN_とhttps://en.wikipedia.org/wiki/International_Article_Number[EANバーコード]の_ @ EAN_制約を偶然提供します。

* 5.3。 URLおよびHTML検証+

*
_ @ Url_制約は、文字列がURLの有効な表現であることを検証します。 さらに、URLの特定のコンポーネントに特定の値があることを確認できます。
@URL(protocol = "https")
private String url;
したがって、プロトコル、ホスト、およびポートを確認できます。 それだけでは不十分な場合、正規表現に対してURLを照合するために使用できる_regexp_プロパティがあります。
プロパティに「安全な」HTMLコードが含まれていることも確認できます(たとえば、スクリプトタグなし)。
@SafeHtml
private String html;
_ @ SafeHtml_はlink:/java-with-jsoup[the JSoup library]を使用します。これは依存関係に含める必要があります。
組み込みのタグホワイトリスト(注釈の_whitelist_プロパティ)を使用し、追加のタグと属性(_additionalTags_および_additionalTagsWithAttributes_パラメーター)を使用して、ニーズに合わせてHTMLサニタイズを調整できます。

*6. その他の制約+

*
Hibernate Validatorには、特にブラジルおよびポーランドの識別番号、納税者コードなどの、国およびロケール固有の制約がいくつか含まれていることを簡単に言及しましょう。 完全なリストについては、http://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#_country_specific_constraints [ドキュメントの関連セクション]を参照してください。
また、_ @ UniqueElements._を使用して、コレクションに重複が含まれていないことを確認できます。
最後に、既存の注釈でカバーされない複雑なケースについては、JSR-223互換のスクリプトエンジンで記述されたスクリプトを呼び出すことができます。 もちろん、最新のJVMに含まれるJavaScript実装であるlink:/java-nashorn[Nashornについての記事]でJSR-223に触れました。
この場合、注釈はクラスレベルにあり、スクリプトはインスタンス全体で呼び出され、変数__this:_として渡されます。
@ScriptAssert(lang = "nashorn", script = "_this.valid")
public class AdditionalValidations {
    private boolean valid = true;
    // standard getters and setters
}
次に、インスタンス全体の制約を確認できます。
bean.setValid(false);
constraintViolations = validator.validate(bean);
assertEquals(1, constraintViolations.size());

7. 結論

この記事では、Bean Validation仕様で定義されている最小セットを超えるHibernate Validatorの制約をリストしました。
これらすべての例とコードスニペットの実装は、https://github.com/eugenp/tutorials/tree/master/persistence-modules/hibernate-mapping/ [GitHubで]にあります。