バリデーションのグルーピング

バリデーションの基本的な使用方法は、以下の記事参照

olafnosuke.hatenablog.com

バリデーションのグルーピングの実装

バリデーションを複数つけているフィールドで、バリデーションの順番を指定したい場合や、条件によってバリデーションする項目や条件を変えたい場合に使用する。

グループ分け用のインターフェースを作成する。

処理などは記述する必要はない。

public interface Group1 {
}
public interface Group2 {
}

グループの順序を指定したい場合は以下のように@GroupSequenceを付与した順番を指定する用のインターフェイスを用意する。
以下の例では、Group1のバリデーションが全てOKになったらGroup2のバリデーションが実行される。

import javax.validation.GroupSequence;

@GroupSequence({ Group1.class, Group2.class })
public interface GroupOrder {
}

バリデーションのアノテーションにgroups属性を追加する

groups属性には複数のグループを指定することもできる。
以下では3つの目的に対してそれぞれアノテーションの記述例を示す。

目的1:バリデーションの順序を指定する

1つのアノテーションにつけた複数のバリデーションの順序を指定するのに使用する場合の記述例は以下の通り。
順序をGroup1→Group2と定義した場合、@NotBlankのチェックがOKになるまで@CodePointLengthのチェックは行われない。

@NotBlank(groups = { Group1.class })
@CodePointLength(min = 3, max = 20, groups = { Group2.class })
private String name;

目的2:グループごとにバリデーションする項目を指定する

以下のように記述した場合、指定するグループの違いによってバリデーションする項目を変えることができる。

@NotBlank(groups = { Group1.class })
private String job;

@NotBlank(groups = { Group2.class })
private String hobby;

目的3:グループごとにバリデーションの条件を変える

以下の記述では、指定するグループの違いによって、同じバリデーションで異なる条件のバリデーションを実行することができる。
※本来同一バリデーションを1つのフィールドに複数記述する場合は@Range.Listを使用するべきであるが、Eclipseを使用しているとエラーが起きてしまう。参考

@Range(min = 0, max = 20, groups = { Group1.class })
@Range(min = 20, max = 100, groups = { Group2.class })
private int age;

グループを指定したバリデーションの実行

@Validatedを使う場合

@Validatedの属性にグループを追加する。複数のグループを指定することもできる。

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;


@Controller
public class SampleController {

    @RequestMapping(value = "/result", method = RequestMethod.POST)
    public String result(@ModelAttribute @Validated({ Group1.class }) SampleModel sm, BindingResult result, Model model) {
        if (result.hasErrors()) {
            model.addAttribute("sm", sm);
            return "index";
        }
        return "result";
    }
}

SmartValidatorを使う場合

SmartValidatorのvalidateメソッドの第3引数以降にグループを追加する。複数のグループを指定することもできる。

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.SmartValidator;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;


@Controller
public class SampleController {

    public SmartValidator validator;

    public ValidationSampleController(SmartValidator validator) {
        this.validator = validator;

    }

    @RequestMapping(value = "/validationResult", method = RequestMethod.POST)
    public String result(@ModelAttribute ValidationSampleModel vm, BindingResult result,
            Model model) {
        validator.validate(vm, result, GroupOrder.class);
        if (result.hasErrors()) {
            model.addAttribute("validationSampleModel", vm);
            return "validationSample";
        }
        return "validationResult";
    }
}