Application Servers & Java

MyBatis selectOne() - TooManyResultsException

midworker 2025. 5. 23. 18:18
반응형

예외 요약

org.mybatis.spring.MyBatisSystemException:
nested exception is org.apache.ibatis.exceptions.TooManyResultsException:
Expected one result (or null) to be returned by selectOne(), but found: 246


문제 요약

항목 내용
원인 selectOne() 호출 시 결과가 2개 이상 반환됨
기대값 0개 또는 1개
실제값 246개
영향 서비스 응답 실패, 예외 전파

오류 발생 조건

sqlSession.selectOne("namespace.methodName", param);

  • 이 쿼리는 정확히 1개의 결과만 기대해야 합니다.
  • 결과가 2개 이상이면 TooManyResultsException이 발생합니다.

실무자가 자주 놓치는 포인트

  1. 쿼리 결과 조건이 불명확

    • WHERE 절 조건이 느슨해 중복을 제거하지 못한 경우
    • 예: country_code = 'KR'만 사용 → 다수 레코드 가능
  2. DB 테이블 중복 데이터

    • 논리적으로 유일해야 할 데이터가 중복되어 있을 수 있음
    • 인덱스 또는 UNIQUE 제약 조건이 누락된 경우 확인 필요
  3. selectOne()을 써야 할지 재검토

    • 애초에 다건 결과가 예상되는 쿼리를 단건 조회로 처리한 경우

해결 방안

  1. 쿼리 수정 – 결과를 하나로 제한

SELECT *
FROM COUNTRY
WHERE CODE = 'KR'
FETCH FIRST 1 ROW ONLY

또는 ORDER BY 정렬 기준을 추가해 가장 적절한 1건만 반환되도록 구성합니다.

  1. 메서드 변경 – selectList()로 다건 결과 처리

List countries = sqlSession.selectList("namespace.methodName", param);

→ 호출 메서드가 selectList()로 바뀌면 예외가 발생하지 않고, 반복문 등으로 처리 가능해집니다.

  1. 데이터 검증
  • SQL 쿼리를 직접 실행해 결과 row 수를 확인해보세요.
  • 논리적 유일 조건을 충족하지 못하는 데이터가 있는 경우, 먼저 DB 정비가 필요합니다.

실무 팁

“A사는 이 문제로 매번 수동으로 selectOne 예외를 수습해야 했고, QA 단계에서도 오류 발생률이 높았음 → 단건 보장 쿼리에 대해 테스트케이스 강화하고, 다건 쿼리는 selectList로 전환하면서 재발 방지.”


추가 정보

  • MyBatis에서 selectOne은 결과가 많을 때 예외를 발생시켜 디버깅을 돕는 설계입니다.
  • XML Mapper 파일에서 resultType이 잘못 지정된 경우도 원인일 수 있습니다.

마무리

selectOne()은 단일 행 반환이 확실한 쿼리에서만 사용해야 합니다.
쿼리 조건이 애매하거나 데이터 정합성이 보장되지 않으면 반드시 쿼리 수정 또는 메서드 교체를 검토해야 합니다.

“배포 전 설정 유효성 검사는 단순 실수로 인한 전체 장애를 방지할 수 있습니다.”


반응형