jdbcTemplate queryForObject 메소드 사용시 매칭되는 data가 없어 null을 return해야 할 때에는 어떻게 처리들 하시나요?

2,535 views
Skip to first unread message

munsu kim

unread,
May 14, 2012, 2:06:01 AM5/14/12
to Korea Spring User Group
사실 오래전부터 궁금했던건데 이제사 질문 드려보아요 ㅠㅠ
try catch를 통해서 null을 return하는게 맞는건지.
애초에 queryForList 메소드를 쓰는 것이 맞는건지...

다른 분들은 어떻게 개발을 하시는지 모르겠으나
일반 JDBC를 사용하던 입장에서는
null 을 return 하는것을 기준으로 클라이언트코드들을(dao를 쓰는 코드..) 작성해왔습니다.

그리고 스프링으로 프로젝트를 진행중이었던 2개정도의 프로젝트를 경험했습니다.
2개의 프로젝트는 각기 다르게 진행을 하였는데요(둘다 JDBCTemplate을 사용하였습니다.)

하나는 DAO 에서 쿼리 결과가 없을 경우 EmptyResultDataAccessException 익셉션을 잡아서 null을
return 하였습니다.
그리고 하나는 queryForList를 사용했었지요.

전 개인적으로 try catch를 통해서 클라이언트 코드에게 null을 return하는 것이 맞는 것 같은데,
여러분은 어떠신가요...?;;

수년전에 논의가 되었던 사항이기도 하지만 궁금하여 여쭈어봅니다 ㅠ

KwonNam Son

unread,
May 14, 2012, 2:23:18 AM5/14/12
to ks...@googlegroups.com
if 조건 대신에 try/catch 예외잡기를 사용하는 것은 성능상 치명적인 문제가 될 수 있는 안티패턴입니다. 관련 논의는 이미 검색해보면 잔뜩나올 것 같네요.
사용하지 마세요.

queryForList()를 사용하시고 그 결과를  http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/dao/support/DataAccessUtils.html DataAccessUtils.uniqueResult() 혹은 singleResult()로 감싸서 리턴하면 바로 해결 됩니다.


2012년 5월 14일 오후 3:06, munsu kim <darksh...@gmail.com>님의 말:

--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.




--
* 까먹지말자! http://kwon37xi.egloos.com

KwonNam Son

unread,
May 14, 2012, 2:25:11 AM5/14/12
to ks...@googlegroups.com
아, 제가 성능상 치명적 문제가 될거라고 했는데, 성능도 성능이지만, 예외라는 것 자체가 "예외적인 상황에"서만 사용하는 것이라서가 더 맞는 이유 같네요.

아무튼 성능에도 안 좋습니다.

2012년 5월 14일 오후 3:23, KwonNam Son <kwon...@gmail.com>님의 말:

munsu kim

unread,
May 17, 2012, 3:47:45 AM5/17/12
to Korea Spring User Group
답변 감사합니다. :)

현재 프로젝트가 급박하다보니 신경을 계속 못쓰고 있었네요.
말씀해주신 부분은 프로젝트 마무리 단계에서 손을 봐야겠어요 ㅠㅠ
웹개발자가 없다보니 jsp로 마무리한 프로젝트를 spring+tiles조합으로 리팩토링하는걸 화면변화가 없다보니 서핑만하고 혼
자 다른 개발일하면서 놀고 있는 줄로 알아서 뭐라도 해야겠네요ㅠㅠㅠ
아, 여기에선 링크가 깨지는데 메일에서는 잘 보이네요. 답변 감사합니다. :)

Sungchul Park

unread,
May 18, 2012, 1:07:25 AM5/18/12
to ks...@googlegroups.com
손권남님의 성능 관련 조언은 정상적인 흐름에서 if를 쓰면 될 부분에 예외를 쓰지 말라는 말이지 예외를 전혀 쓰지 말라는 의미는 아니라고 봅니다. 자바가 예외를 발생는 비용도 많이 들고 예외 처리 코드 블럭을 최적화하지 않아서 느리기는 하지만 예외는 말 그대로 예외적인 상황을 의미하므로 특별한 경우가 아니라면 성능에 영향을 줄 정도는 아닙니다.

예외의 성능 관련 문제는 이 페이지를 참고하세요.

http://stackoverflow.com/questions/299068/how-slow-are-java-exceptions

위 페이지의 James Schek이 쓴 글에서 언급된 것처럼, 엄청나게 큰 파일을 읽어 그에 적힌 값들이 정상적인지 확인할 때에 Integer.ParseInt(...)를 사용하는 것 같은 상황이 대표적인 예외의 안티패턴인 거겠죠.

본론으로 돌아가서... queryForObject의 결과가 없을 때 EmptyResultDataAccessException을 내는 게 맞냐는 건데요.저도 처음에 질의 결과가 없는 게 왜 예외 상황인가 당황했었습니다. 하지만 생각해보니, 특정 ID(또는 키) 값으로 꼭 집어서 데이터를 꺼내오는데 해당 데이터가 없다면 뭔가 문제가 생긴 예외 상황으로 봐도 되지 않나 싶습니다.

결국 null을 반환할지, 예외를 던질지는 설계 상 선택의 문제겠지만, 예외를 던지는 결정에도 나름의 의미가 담겨 있다고 생각합니다.

queryForObject(...) 중 하나를 보면 소스가 이렇습니다.

    public <T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException {
        List<T> results = query(sql, args, new RowMapperResultSetExtractor<T>(rowMapper, 1));
        return DataAccessUtils.requiredSingleResult(results);
    }
EmptyResultDataAccessException을 내는 곳은 DataAccessUtils.requiredSingleResult(...) 안 입니다. 매개변수로 받은 집합에서 첫번째 항목을 반환하는데, 만약 받은 집합이 공집합이면 이 예외를 내는 거죠. JdbcTemplate 설계자는 queryForObject의 경우 반드시 하나의 결과가 있어야 한다(requiredSingleResult)고 생각한 것 같습니다.

즉 queryForList는 "조건에 맞는 데이터 전부"의 의미라면 queryForObject은 "바로 그 데이터"의 의미인 거죠.

참고로, 반환값이 있을 수도 있고 없을 수도 있을 때, null 같이, 값을 되돌려 받는 측에서 반드시 이를 확인하지 않으면 문제가 생길 수도 있는 상황을 피하기 위해 스칼라에서는 Option이란 객체를 사용합니다. 제가 자바용으로 만든 것을 gist에 올려놨었는데 참고하세요.

https://gist.github.com/1263813


12. 5. 14. 오후 3:06, munsu kim 쓴 글:
Reply all
Reply to author
Forward
0 new messages