@Embeddable 사용 시 NullPointerException에 대비하기

1. 개요

문득 DB의 Member 테이블을 보던 중 너무 많은 Null 값이 존재하는 게 신경 쓰였다. 

회원의 Role은 기업, 노동자로 나눠져있고 각 Role마다 갖는 필드가 다르기 때문에 @Embeddable로 관리하고 있었다. 

그렇다 보니 기업은 노동자가 갖는 컬럼은 전부 null이고, 노동자는 기업이 갖는 컬럼은 전부 null이었다. 

 

프로젝트에선 Spring Data JPA의 기본 구현체인 Hibernate를 사용하고 있는데, Hibernate 구현체에선 @Embedded 객체의 모든 필드의 값이 null이면 해당 객체 자체를 null로 설정하게 된다.

따라서 해당 클래스를 사용하려고 할때 NullPointerException이 발생해버린다.

 

이를 해결하기 위해선 2가지 방법으로 해결할 수 있다. 

 

 

 

 

 

 

해결 - 1. Null일 수 없는 값을 값 사용

예를 들어 생성되는 날짜가 Embeddable 내에 반드시 포함되게 하여 최소한 값 하나는 null이 되지 않도록 하는 방법을 이용해서 하는 방법이 있을 수 있고

@Column(updatable = false)
@CreatedDate 
private LocalDateTime createdDate;

 

 

더미 데이터를 Embeddable 내에 포함되게 하여 null이 되지 않도록 하는 방법이 있다.

@Formula("25")
private int age;

 

 

 

 

 

 

해결 - 2. yml 설정

이 문제는 이미 많은 사람들이 겪었고 이에 대한 논의가 활발하게 이루어졌다. 결국 Hibernate에서 해당 설정을 변경할 수 있게 2016년 5.1 패치로 수정하게 되었다.

 

 

 

 

나는 간단하게 yml 설정으로 NullPointerException이 터지는걸 막아줬다.

spring:
  jpa:
    properties:
      hibernate:
        create_empty_composites:
          enabled: true

 

 

기업 계정으로 로그인 후 요청을 보내고, 값이 전부 null인 workerInfo embedded 객체에 접근했을 때 예외가 터지는 지 간단하게 테스트해봤다. 

@GetMapping("/null-test")
public String test(@AuthenticationPrincipal PrincipalDetails principalDetails) {
    Member member = memberRepository.findById(principalDetails.getMember().getId()).get();
    System.out.println(member.getWorkerInfo().getWorkerName());
    return "test";
}

 

 

yml 설정 전

 

yml 설정 후

 

 

embedded 객체의 필드들이 전부 null이더라도 embedded 객체 자체는 null로 저장되지 않는 걸 확인할 수 있다.