springframework/Spring Data JPA

Spring Data Common : Null 처리

Jungsoomin :) 2020. 11. 15. 19:42

Spring Data 2.0 부터 Java 8 부터 나온 Optional 을 제공한다.

  • 리턴 타입이 하나일 경우 Optional<T> 선언이 가능하다.

리턴타입이 하나일 경우 Optional<T> 사용이 권장된다.

  • null 처리에 대한 코드를 줄이고 null 상황에 따른 동작의 기댓 값을 직관적으로 확인할 수 있다.
  • 다만, JPA 리턴타입이 컬렉션일 경우 Empty 상태의 컬렉션이 리턴되므로 주의한다.
@NoRepositoryBean
public interface MyRepository<T, Id extends Serializable> extends Repository<T, Id> {

    // T 의 하위타입 E
    <E extends T> E save( E entity);

    List<T> findAll();

    long count();

    <E extends T> Optional<E> findById(@NonNull Long id);

}

Optional<T> = get(), orElse(), orThrow() 등 다양한 null 상황에 대한 기댓값을 확인할 수 있다.

@RunWith(SpringRunner.class)
@DataJpaTest
public class CommentRepositoryTest {

    @Autowired
    private CommentRepository commentRepository;

    @Test
    @Rollback(false)
    public void optional(){
        //Given
        Comment comment = new Comment();
        comment.setComment("Hello Spring Data Optional");

        // Persistent
        Comment save = commentRepository.save(comment);

        //When
        Optional<Comment> findComment = commentRepository.findById(save.getId());

        //Then
        assertThat(findComment).isNotEmpty();
        assertThat(findComment.orElseThrow(IllegalArgumentException::new).getComment()).isEqualTo("Hello Spring Data Optional");
    }
}
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        comment
        (comment, post_id, id) 
    values
        (?, ?, ?)
2020-11-15 19:38:32.174 TRACE 12572 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [Hello Spring Data Optional]
2020-11-15 19:38:32.176 TRACE 12572 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [BIGINT] - [null]
2020-11-15 19:38:32.177 TRACE 12572 --- [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [BIGINT] - [1]

Spring Data JPA 의 컬렉션은 null 이 아닌 Empty 상태로 리턴된다.

  • 즉, Spring Data JPA 메서드 리턴 값이 컬렉션 일경우 null 체크는 무의미하다.

Spring Framework 5.0 버전 부터 지원하는 Null Safety 를 지원한다.

  • IDE 에서 널 체킹을 해준다.
  • 런타임 시에 Null 체킹을 해준다.

이 부분은 Spring Framework 핵심기술에 기술되어 있다. 최대 강점은 IDE 선에서 Null 여부를 체크해 주어 런타임에 일어날 실수를 미연에 방지시켜준다는 것이라고 생각한다.

@NoRepositoryBean
public interface MyRepository<T, Id extends Serializable> extends Repository<T, Id> {

    // T 의 하위타입 E
    <E extends T> E save(@NonNull E entity);

    List<T> findAll();

    long count();

    @Nullable
    <E extends T> Optional<E> findById(@NonNull Long id);

}