@Basic
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface Basic {
/**
* (Optional) Defines whether the value of the field or property should
* be lazily loaded or must be eagerly fetched. The <code>EAGER</code>
* strategy is a requirement on the persistence provider runtime
* that the value must be eagerly fetched. The <code>LAZY</code>
* strategy is a hint to the persistence provider runtime.
* If not specified, defaults to <code>EAGER</code>.
*/
FetchType fetch() default EAGER;
/**
* (Optional) Defines whether the value of the field or property may be null.
* This is a hint and is disregarded for primitive types; it may
* be used in schema generation.
* If not specified, defaults to <code>true</code>.
*/
boolean optional() default true;
}
@Entity 내의 필드에 기본값이 암시적으로 사용되며 Hibernate가 영속성을 위해 매핑할때 사용된다.
Optional 속성은 표시된 필드의 null을 허용하는지 여부를 나타낼 수 있고, Fetch 속성은 해당 필드를 LAZY, EAGER 중 컨트롤 할 수 있게 한다. 디폴트로 null 허용, 즉시로딩을 갖고 있고 바꾸고 싶다면 어노테이션과 함께 옵션을 사용한다.
@Column은 DB에 적용되는 내용이고 @Basic은 엔티티(자바 JPA)에 적용되는 내용이다.
Validator, InitBinder
Validator Interface
public interface Validator {
boolean supports(Class<?> clazz);
void validate(Object target, Errors errors);
}
supports() : 검증하려는 클래스를 체크하는 메소드
validate() : validate 로직, 유효하지 않을 때 errors에 에러 추가
해당 인터페이스를 구현하고 WebDataBinder를 통해 등록해서 사용한다.
@Controller
@RequiredArgsConstructor
public class AccountController {
private final SignUpFormValidator signUpFormValidator;
private final AccountService accountService;
@InitBinder("signUpForm") // () 안 value에 해당하는 객체를 파라미터로 받을 때 검증로직 동작
public void initBinder(WebDataBinder webDataBinder) {
webDataBinder.addValidators(signUpFormValidator); // Validator 구현체 WebDataBinder에 추가
}
@GetMapping("/sign-up")
public String signUpForm(Model model) {
model.addAttribute("signUpForm", new SignUpForm());
return "account/sign-up";
}
@PostMapping("/sign-up")// singUpForm을 파라미터로 받을 때 검증로직 거친 후 컨트롤러로 이동
public String signUpSubmit(@Valid SignUpForm signUpForm, Errors errors) {
if (errors.hasErrors()) { // 검증로직을 거친 Errors 포함
return "account/sign-up";
}
accountService.signUp(signUpForm);
// TODO 회원 가입 처리
return "redirect:/";
}
}
해당의 과정을 DTO 필드에 어노테이션(ex: @NotBlank, @Length..)을 붙이고 컨트롤러에서 @Valid 이용하게끔 추상화된 것이다.
MVC Controller Test
MockMvc가 Model과 View에 대한 테스트도 지원한다.
// Controller
@GetMapping("/sign-up")
public String signUpForm(Model model) {
model.addAttribute("signUpForm", new SignUpForm());
return "account/sign-up";
}
// Controller Test
@Test
@DisplayName("회원 가입 화면 테스트")
public void signUpForm() throws Exception {
mockMvc.perform(get("/sign-up"))
.andExpect(status().isOk()) // HttpStatusCode 확인
.andExpect(view().name("account/sign-up")) // view 이름 확인
.andExpect(model().attributeExists("signUpForm")); // model 확인
REST API 처럼 빡센 응답 값 테스트는 어렵지만 테스트 가능하다는 것을 알았다.
참고
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-JPA-%EC%9B%B9%EC%95%B1/dashboard