0
0

More than 1 year has passed since last update.

validation @Maxと@Minを使って、日付データを制御する

Posted at

bean validationとは、springで有効性検証のための標準、アノテーションベースの制約条件で簡単に検証できます。
bean validationが提供するアノテーションを使って日付データを除去してみようと思います。

validationを適用していない挙動

テストコード、givenPersonのsetBirthdayに存在しない日付をセットするようにして挙動を確認する。
テストコード
@Test
void findByBirthdayBetween() {
     givenPerson("martin",10,"A",LocalDate.of(1991,2,21));
     givenPerson("david",9,"B",LocalDate.of(1992,7,1));
     givenPerson("dennis",8,"O",LocalDate.of(1993,1,5));
     givenPerson("sophia",7,"AB",LocalDate.of(1994,6,30));
     givenPerson("benny",6,"A",LocalDate.of(1995,8,30));

     List<Person> result = personRepository.findByMonthOfBirthday(14);

     result.forEach(System.out::println);
}

private void givenPerson(String name, int age, String bloodType, LocalDate birthday) {
    Person person = new Person(name, age,bloodType);
    person.setBirthday(new Birthday(birthday.getYear(), 14, 35));
    personRepository.save(person);
}
生年月日DTOクラス
package com.informanaging.project.demo.domain.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Embeddable;
import java.time.LocalDate;

@Embeddable
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Birthday {
    private int yearOfBirthday;
    private int monthOfBirthday;
    private int dayOfBirthday;
}
Personエンティティクラス
package com.informanaging.project.demo.domain;

import com.informanaging.project.demo.domain.dto.Birthday;
import lombok.*;
import javax.persistence.*;
import javax.validation.Valid;
import java.time.LocalDate;

@Entity
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Data
public class Person {
    // ・・・省略
    @Embedded
    private Birthday birthday;
}

結果が以下。ユーザーから存在しない日付を入力してもらってもエラーにならず、動いてしまいます。
image.png

validationを適用する

Springでvalidationを使うためには、dependencyを追加する必要があります。

build.gradle
 implementation 'org.springframework.boot:spring-boot-starter-validation'

日付の月データは1~12の間の値を持てるし、日データは1~30の間の値を持てますので、その定義をまず
やります。この場合に使えるvalidationのannotationはminとmaxがあります。
以下のように@min(数値) @max(数値)のように使うことができます。

また、エンティティクラスにはbirthdayについて@Validを定義する必要があります。

生年月日DTOクラス
package com.informanaging.project.demo.domain.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Embeddable;
import java.time.LocalDate;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;

@Embeddable
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Birthday {
    @Min(1)
    @Max(12)
    private int monthOfBirthday;

    @Min(1)
    @Max(31)
    private int dayOfBirthday;
    private int dayOfBirthday;
}
Personエンティティクラス
package com.informanaging.project.demo.domain;

import com.informanaging.project.demo.domain.dto.Birthday;
import lombok.*;
import javax.persistence.*;
import javax.validation.Valid;
import java.time.LocalDate;
import javax.validation.Valid;

@Entity
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Data
public class Person {
    // ・・・省略
    @Valid
    @Embedded
    private Birthday birthday;
}

修正後のテスト結果。
image.png
しかしこれだけだと、2月30日のデータも正しいデータだとプログラムは認識してしまうので、
追加修正が必要です。
image.png

BirthdayDTOクラスにBirthday constructorを設けて、受け取るBirthdayデータをLocalDataにてラッピングします。
LocalDateをラッピングすると、渡されるデータが実際に存在しないデータだとエラーを吐き出します。
そのため、実はMinとMaxの対応も要らなくなります。

birthdayデータをLocalDateにてラッピングする
package com.informanaging.project.demo.domain.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Embeddable;
import java.time.LocalDate;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;

@Embeddable
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Birthday {
    private int yearOfBirthday;

    @Min(1)
    @Max(12)
    private int monthOfBirthday;

    @Min(1)
    @Max(31)
    private int dayOfBirthday;

    public Birthday(LocalDate birthday) {
        this.yearOfBirthday = birthday.getYear();
        this.monthOfBirthday = birthday.getMonthValue();
        this.dayOfBirthday = birthday.getDayOfMonth();
    }
}
テストコード、setBirthdayにセットするデータ型も修正。
    private void givenPerson(String name, int age, String bloodType, LocalDate birthday) {
        Person person = new Person(name, age,bloodType);
        person.setBirthday(new Birthday(birthday));
        personRepository.save(person);
    }
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0