Loading

ROUTE

ルートゼロの
アクティビティ

Spring Bootの@Validと@Validatedの違い

1

Spring Bootで入力チェックを書くと、`@Valid`と`@Validated`のどちらを使うか迷うことがあります。通常のBean Validationなら`@Valid`で十分な場面が多く、Validation Groupsを明示して検証対象を切り替えたいときはSpringの`@Validated`が使いやすい、というのが基本の判断です。

まず比較:@Validと@Validatedの違い

観点 @Valid @Validated
提供元 Jakarta Validation Spring Framework
基本Validation できる できる
Validation Groups指定 Annotation自体では指定しない valueでGroupを指定できる
ネストObjectのcascade 主な用途の1つ 必要に応じて@Validと組み合わせる
典型用途 通常の入力Object検証 Groupを切り替える検証・Springのmethod validation

Spring MVCでは、`@RequestBody`などのmethod parameterに`@Valid`または`@Validated`を付けるとStandard Bean Validationを適用できます。違いが大きく出るのは、Validation Groupを使うときです。


@ValidはJakarta Validationの標準Annotation

`@Valid`はSpring固有ではなくJakarta Validation側のAnnotationです。Controllerの入力ObjectやネストしたObjectへValidationを伝播させる用途で使われます。

public record CreateUserRequest(
    @NotBlank String name,
    @Email String email
) {}

@PostMapping("/users")
public void create(@Valid @RequestBody CreateUserRequest request) {
    // validation passed
}

(まず@Validを使ったSpring Bootの基本Validationを確認したい場合については『Spring Bootのフォームバリデーションとは?@Validで安全な入力チェックを実現しよう』をご参照ください)


@ValidatedはSpringのAnnotationでGroupsを指定できる

`@Validated`はSpring FrameworkのAnnotationです。Springの`SmartValidator`へvalidation hintを渡す仕組みを使い、Validation Groupのclassを指定できます。登録時と更新時で検証ルールを変えるようなケースで便利です。

public interface CreateGroup {}
public interface UpdateGroup {}

public class UserRequest {
    @NotBlank(groups = CreateGroup.class)
    private String name;

    @NotNull(groups = UpdateGroup.class)
    private Long id;
}
@PostMapping("/users")
public void create(
    @Validated(CreateGroup.class) @RequestBody UserRequest request
) {
}

@PutMapping("/users/{id}")
public void update(
    @Validated(UpdateGroup.class) @RequestBody UserRequest request
) {
}

Validation Groupsは『同じDTOの検証条件を切り替える』仕組み

Jakarta Validationでは、各constraintを1つ以上のGroupへ所属させられます。Groupを指定しないconstraintはDefault groupに属します。Create/Updateのように状態ごとに必要なconstraintが違う場合、Groupを使って検証対象を切り替えられます。

ケース 向く方法
全操作で同じconstraint Default group + @Valid
作成時だけ必須 CreateGroup + @Validated
更新時だけ必須 UpdateGroup + @Validated
ネストObjectも検証 @Validによるcascadeを確認

Controllerではmethod validationとの違いにも注意する

Spring MVCの現行仕様では、Request ObjectのValidationと、method parameterへ直接`@NotBlank`や`@Min`などを付けるmethod validationは別の経路です。直接constraintがある場合はmethod validationが適用され、`HandlerMethodValidationException`が使われるケースがあります。

またSpring Framework 6.1以降のMVC built-in method validationを使うControllerでは、class-levelの`@Validated`を外すよう公式ドキュメントで案内されています。Service層などAOPを使うmethod validationとは区別して考えます。

よくある混同:@Validatedに変えればValidationが直るわけではない

Validationが効かない原因がdependency不足、constraintの付け忘れ、BindingResultの扱い、method signatureなどにある場合、`@Valid`を`@Validated`へ置き換えるだけでは解決しません。Groupsが必要なのか、そもそもValidationが発火していないのかを分けて確認します。

(Validation自体が動かない場合の確認ポイントについては『Spring Boot バリデーション効かない?5分で直す方法』をご参照ください)

使い分けの判断基準

  • 通常のRequest Object検証ならまず@Valid
  • Create/UpdateなどGroupを指定するなら@Validated(Group.class)
  • ネストObjectのcascadeは@Validの有無を確認
  • Controllerのmethod parameterへ直接constraintを置く場合はmethod validationの例外経路も確認
  • Annotationを変える前に、何を切り替えたいのかを明確にする

現在のDTOでCreateとUpdateのconstraintが混在しているなら、まずGroupに分ける必要があるかを確認してから`@Validated`を導入してみてください。

カジュアル面談はこちら

すべてを開示している会社です

ポジティブな面もネガティブな面も、包み隠さず誠実にお答えします。
気になることがあれば、面談の際にすべてオープンにお話します。