[JPA] nullable = false와 @NotNull의 차이점

ds_chanin

·

2019. 5. 6. 23:24


지금 보시는 이글은 정확하지 않습니다. 곧 수정예정입니다.

nullable = false vs. @NotNull

친구들과 스프링 부트를 공부하던 도중 한 친구가 내 코드를 보고

저번에는 @NotNull을 쓰던데 이번에는 nullable = false를 쓴 이유가 무엇이냐고 물어봤다.

 

둘다 내가 원하는 대로 동작한다고 생각만했다.

와,, 깊이 생각해 본적이 없었다!

 

그래서 바로 찾아봤다!

 

 

 

 

nullable = false

관련 레퍼런스에서 설명을 보려했는데 JPA레퍼런스가 다 영어라서 어디로 가야할지 모르겠다..

그래서 코드에서 정의되어있는 부분을 확인해 보았다.

 

/**
 * (Optional) Whether the database column is nullable.
 */
boolean nullable() default true;

 

설명 대로라면 nullable 은 DDL에 적용된다.

default값은 true이고 false로 설정하면 DDL 생성 시 not null 제약 조건이 붙는다.

 

@NotNull

https://docs.spring.io/spring/docs/4.1.x/spring-framework-reference/html/validation.html

에 가보니 스프링 프레임워크 4.0가 지원하는 Bean Validaion(JSR-303)이라고 적혀있다.

 

이렇게만 적혀있는거만 봐서는 어떻게 작동하는지 당연히 모른다.

https://docs.jboss.org/hibernate/beanvalidation/spec/2.0/api/

이곳에 상세하게 설명이 적혀있는데

The annotated element must not be null. Accepts any type.

 

이 어노테이션이 적혀있는 요소는 절대로 Null값이 들어갈 수 없다. 라고 적혀있다.

 

 

확인해보자

테스트에 사용된 엔티티는 다음과 같다.

 

Account.java

@Entity
@Table(name = "ACCOUNT")
@Getter
@NoArgsConstructor
public class Account {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ACCOUNT_ID")
    private Long id;

    @Column(name = "ACCOUNT_EMAIL", unique = true)
    private String email;

    @Column(name = "ACCOUNT_PASSWORD")
    private String password;

    @Column(name = "ACCOUNT_NAME")
    private String name;

    public Account(String email, String password, String name) {
        this.email = email;
        this.password = password;
        this.name = name;
    }
}

 

 

각 멤버변수에 nullable = false 만 설정한 후 테스트를 해보았다.

 

 

AccountTest.java

@SpringBootTest
@RunWith(SpringRunner.class)
public class AccountTest {

    @Autowired
    AccountRepository accountRepository;

    String email;
    String password;
    String name;
    Account account;

    @Before
    public void setUp() throws Exception {
        password = "1234";
        name = "박찬인";
    }

    @Test
    public void 컬럼_정상입력_테스트() {
        email = "pci2676@gmail.com";
        account = new Account(email, password, name);
        assertThat(accountRepository.save(account));
    }

    @Test
    public void 컬럼_공백입력_테스트() {
        email = "cip0508@naver.com";
        account = new Account(email, password, "");
        assertThat(accountRepository.save(account));
    }

    @Test
    public void 컬럼_NULL입력_테스트() {
        email = "example@gmail.com";
        account = new Account(email, password, null);
        assertThat(accountRepository.save(account));
    }

}

 

nullable = false로 했더니

 

DDL에서 not null 설정이 적용되어 테이블이 생성됨을 확인 할 수 있었다.

 

테스트 코드의 실행결과를 보니

 

빈 문자열의 입력은 허용하지만 null값을 입력할 경우 데이터베이스 insert하는 과정에서 에러가 발생하였다.

DDL에서 not null로 설정되었으니 당연한 결과이다!

 

 

이번에는 @NotNull을 설정한 후 테스트를 해보았다.

@NotNull 어노테이션도 DDL에서 not null 속성이 설정되는 것을 확인 할 수 있었다!

 

 

테스트 결과는 다음과 같았다.

 

 

@NotNull또한 공백입력은 허용하지만 NULL입력은 다음과 같이 유효성 검증 과정에서 오류를 발생시켰다.

 

 

 

 

 

결론

@NotNull 은 유효성 검사를 해주기 때문에 위와 같이 비어 있는 값이 들어가서는 안된다는 에러가 나오지만

데이터베이스의 제약조건과는 관계가 없어 보였다. 하지만 좀더 찾아보니 이런 제약조건을 해석하여 데이터베이스에 자동으로 not null 제약 조건을 걸어준다!

 

nullable = false 는 데이터베이스에 명시적으로 not null 제약 조건을 걸어준다. 하지만 유효성 검사는 해주지 않는다!

 

@NotNull을 이용하는 것이 제약조건 설정유효성 검사를 같이 해주기때문에 조금 더 안전하게 사용할 수 있을것 같다.