Springの@Validと@Validatedの違いを完全ガイド!初心者でもわかるバリデーションの使い分け
生徒
「Springのバリデーションで@Validと@Validatedって両方見かけますけど、何が違うんですか?」
先生
「どちらもBean Validationを実行するアノテーションですが、使える場所や機能に違いがあるんですよ。」
生徒
「どっちを使えばいいのかいつも迷ってます…。ControllerでもServiceでも使えますよね?」
先生
「それでは、@Validと@Validatedの違いや、Controller・Service・ネストされたオブジェクトでの使い分け方を見ていきましょう。」
1. @Validと@Validatedの基本的な違い
@Validはjavax.validationパッケージの標準アノテーションで、Java Bean Validationの仕様に従って入力チェックを行います。Springフレームワークに特化していないため、基本的なバリデーションしかできません。
@Validatedはorg.springframework.validation.annotationに属するSpring独自のアノテーションで、グループ化されたバリデーションの実行や、Service層などでの使用にも柔軟に対応できます。
2. Controllerでの使い方:どちらも使えるが@Validで十分なケースが多い
Spring MVCのControllerでは、通常は@Validを使ってバリデーションを実行するのが一般的です。以下はその例です。
@PostMapping("/register")
public String register(@Valid UserForm form, BindingResult result) {
if (result.hasErrors()) {
return "formPage";
}
return "success";
}
ControllerではSpringが裏側でMethodValidationPostProcessorなどを適用してくれるため、@Validでも@Validatedでも違いはほとんど出ません。
3. Service層で使うなら@Validatedが必須
ServiceやComponentなど、SpringのDIコンテナで管理されるクラスでメソッド引数にバリデーションをかけたい場合は@Validatedが必要です。@Validでは動作しません。
@Service
@Validated
public class UserService {
public void saveUser(@Valid UserForm form) {
// この@Validは@Validatedで有効になる
}
}
ServiceやRepositoryなどに直接バリデーションを適用する場合は、必ずクラスに@Validatedを付与する必要があります。
4. ネストされたオブジェクトのバリデーション
フォーム内にネストされたオブジェクト(例:住所など)がある場合、フィールドに@Validを付けておくことで、子オブジェクトのバリデーションも実行されます。
public class UserForm {
@NotBlank
private String name;
@Valid
private AddressForm address;
}
このように@ValidはネストされたBeanに対して有効です。@Validatedはネストの検証には使用できません。
5. グループバリデーションは@Validatedだけが対応
バリデーショングループを使うと、シチュエーション別に異なるルールを適用できます。この機能は@Validatedのみ対応しており、@Validでは使用できません。
public class UserForm {
@NotNull(groups = Create.class)
private String username;
@NotNull(groups = Update.class)
private String email;
}
呼び出し元でバリデーショングループを指定する場合は、次のように@Validated(Create.class)のように書きます。
@PostMapping("/create")
public String create(@Validated(Create.class) UserForm form, BindingResult result) {
// Createグループに対してのみバリデーション実行
}
6. Controllerで使う時の選び方
基本的にControllerで使うバリデーションには@Validを使えば問題ありません。ただし、バリデーショングループを使いたい場合や、ServiceやRepositoryでも同じオブジェクトをバリデートしたい場合は、@Validatedを使うようにするとよいでしょう。
7. 実行タイミングや注意点の違い
Controllerでの@Validは、HTTPリクエスト受け取り時点でバリデーションが走るのに対し、Service層ではAOP的に@Validatedで動作します。そのため、DIされていないクラスなどでは動かないこともあります。
また、Spring Bootで@Validatedを使うには、spring-boot-starter-validationの依存関係が必要なので注意しましょう。
8. テストコードでの使い分けについて
単体テストでDTOなどのバリデーションを手動でチェックする場合は、javax.validation.Validatorを使って検証できます。ここでも@Validatedを使うことで、グループごとの検証が可能です。
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<UserForm>> violations = validator.validate(form, Create.class);