Posts [Spring] JdbcTemplate queryForObject() - Return Value Issue
Post
Cancel

[Spring] JdbcTemplate queryForObject() - Return Value Issue

Introduction

회고 프로젝트에서 DB 레코드를 조회하는 로직을 구현했다.
이때, 파라미터로 넘어오는 id를 기준으로 findById()를 작성했다.
해당 메소드에서 Optional을 반환하게 만들었는데, 여기서 예외 핸들링을 제대로 해주지 않아 문제가 발생했다.
어떤 문제였고 어떻게 해결했는지 간단하게 정리하려 한다.

Issue

1
2
3
4
5
6
7
public Optional<Member> findById(Long id) {
    String query = "SELECT id, name FROM MEMBER WHERE id = ?";

    return this.jdbcTemplate.query(query, ROW_MAPPER, id)
            .stream()
            .findAny();
}

다른 크루가 기존에 작성했던 코드이다.
나는 이 메소드에서 어색한 부분을 느꼈다.
하나의 Member를 반환하는데 왜 queryForObject()가 아닌 query()를 사용했지? 란 생각이 들었다.


1
2
3
4
5
public Optional<Member> findById(Long id) {
    String query = "SELECT id, name FROM MEMBER WHERE id = ?";

    return Optional.ofNullable(this.jdbcTemplate.queryForObject(query, ROW_MAPPER, id));
}

그래서 위와 같이 변경했다.
쿼리 결과가 null일 수 있으니까 Optional.ofNullable()을 활용했다.
조회 시 데이터가 없으면 Optional<null>이 반환될 거라 생각했다.

근데, 완전히 잘못 생각하고 있었다.
오히려 EmptyResultDataAccessException이 발생했다.


1
2
3
4
5
6
7
8
9
public Optional<Member> findById(Long id) {
    String query = "SELECT id, name FROM MEMBER WHERE id = ?";

    try {
        return Optional.ofNullable(this.jdbctemplate.queryForObject(query, ROW_MAPPER, id));
    } catch (EmptyResultDataAccessException e) {
        return Optional.empty();
    }
}

해당 코드처럼 try-catch 구문으로 조회 결과가 없으면 예외를 잡도록 구현해야 했다.
catch 문에서는 Optional.empty()를 반환한다.
조회 결과로 null이 나오는 경우는 해당 데이터에 null이 들어있을 때 같다.

나는 이 부분에서 try-catch 구문을 꼭 써야 할까? 의문이 들었는데,
손너잘과 얘기한 뒤 한번은 쓸 수 밖에 없다고 결론지었다.

손너잘이 DAO에 try-catch 구문을 안 쓸 수 있는 방법도 소개해줬다.

JdbcTemplate을 감싸는 다이나믹 프록시를 생성하고, 여기서 try 구문으로 queryForObject()를 수행하고, 예외가 발생하면 catch 구문으로 Optional.empty()를 반환하게 한다.

아무튼 최소 한번은 try-catch 구문이 필요하다.

이런 흐름으로 문제 해결을 완료했다!

This post is licensed under CC BY 4.0 by the author.

[우아한테크코스] 기본 생성자가 필요한 이유 (Why the default constructor is needed) (feat. Jackson ObjectMapper + Reflection)

[Java] Gradle Dependency Configurations