⚡ 개요
DB에서 테이블 생성할 때 Default 값을 설정했지만 값이 null로 들어가 있는 상황이 발생을 하게 되었고 기본값을 사용하는 과정에서 NPE 발생하게 되었다. 이에 따른 내용을 정리하려고 한다.
내부 로직에서 저장하는 부분을 찾아보니 repository에서 save() 함수를 통해서 저장을 하고 있었다. Entity에서도 Default을 설정 했는데 왜 기본값으로 저장이 안 되고 null로 저장이 되는지 한번 알아보자.
⚡ 내용
Entity 일부
코드를 살펴보면 @colunmDefault() 어노테이션을 사용해서 기본값을 설정한 부분을 볼 수 있다. nullable은 설정하지 않았기 때문에 실제 DB에 값은 null로 들어갈 수도 있었다.
@colunmDefault() 에 대해서 문서를 찾아보면 알겠지만 해당 어노테이션을 선언한다고 해서 기본값으로 넣어주는 게 아니라는 것을 알 수 있다. 그냥 저 값을 기본값으로 넣어야 된다고 알려주는 것뿐이다.
save() 함수 호출 시 로그
테스트 코드를 작성해서 save()를 호출 테스트를 진행한 결과 모든 필드에 대해서 insert를 하게 된다. 정의를 하지 않은 필드의 경우는 null로 들어가게 되며 기본값이 들어가지 않게 된다.
그렇다면 기본값을 넣으려면 어떻게 해야 하는지 방법에 대해서 찾아보았다.
💡 방법 1
@DynamicInsert
해당 어노테이션을 Entity에 선언하는 것이다. 선언을 하게 되면 null인 값들은 insert 시점에 빠지게 된다. 아래의 이미지를 보면 이해가 될 것이다.
위의 어노테이션 말고도 DynamicUpdate 어노테이션도 있다.
모든 필드에 대해서 insert 및 update를 하는 이유에 대해서도 궁금해서 찾아보았다. 간단하게 한 줄 요약하자면 DB에 데이터를 보내는 전송량에 대해서 불합리할 수는 있지만, 재사용 측면에서는 좀 더 효율적인 거 같았다. (세부적인 내용을 파악하려면 구현체가 어떻게 동작하고 관리하는지를 봐야 하는데 한번 찾아보면 좋다.)
💡 방법 2
@PrePersist
해당 어노테이션도 Entity에서 선언을 하고 사용할 수 있다. 선언을 하고 사용하게 되면 Entity가 저장 전에 JPA Provider에 의해서 자동으로 호출이 된다. (해당 어노테이션 말고 @PreUpdate 어노테이션도 있다.)
나는 위의 방법처럼 사용했으며, 상황에 맞게 사용하면 될 거 같다. (장단점이 분명히 존재한다. 필요한 상황이 온다면 그냥 쓰지 말고 한 번쯤 찾아보고 사용하는 것을 추천한다.)
위 두 개의 어노테이션을 동시에 사용한 로그이며, 기본값이 들어가는것을 볼 수 있다.
💡 추가 방법
위의 방법 두개 말고도 다른 방법도 있다. 네이티브 쿼리를 사용하는 것이다. (이미지 참조)
네이티브 쿼리를 사용했을 때 분명 성능적인 측면에서는 훨씬 이득이지만 아래와 같이 모든 코드를 작성한다고 하면 너무 귀찮고 끔찍하다. 상황에 맞게 잘 사용하는 게 중요하다고 생각한다.
Default 값을 넣는 방법에 대해서 간단하게 정리를 했다. 사용법은 매우 간단해서 쓰는 데는 문제가 없지만 장단점에 대해서 아니면 어노테이션이 어떻게 동작하고 있는지는 사용 전에 한 번쯤 공부하고 쓰면 좋을 거 같다.
'Spring' 카테고리의 다른 글
[QueryDSL] SQLQueryFactory 사용시 LocalDate 타입 반환시 날짜 에러 (0) | 2024.06.01 |
---|---|
Spring boot + vue 프로젝트 (2) (0) | 2024.04.06 |
Spring boot + vue 프로젝트 (1) (0) | 2024.04.04 |
[JPA] Spring boot 3.x.x 에서 QueryDsl Date Type 사용 방법 (0) | 2024.01.09 |
[Spring] Spring boot 3.x.x 버전 마이그레이션 내용 정리 (0) | 2023.12.31 |