본문 바로가기

오류일기

Data Jpa의 exists에 대한 고찰

현상

현장 실습중 인자의 리스트의 값이 DB에 모두 있어야만 True가 반환되는 로직을 구현해야 할 일이 생겼다.

나는 현장실습에서 사용중인 data jpa를 통해 해당 로직을 구현하였다.

나는 다음과 같이 메서드를 data jpa의 메서드 네이밍 컨벤션에 따라 작성하였다.

Boolean existsAllByIdIn(List<Long> ids);

이후 해당 로직이 올바르게 동작하는지 테스트를 해보았지만 이상한 점을 찾았다.

내가 원하는 로직은 인자로 주어지는 값이 DB에 모두 있어야지만 true를 반환하는 것이지만 실제로 동작할때는 하나라도 값이 있으면 true를 반환하는 식으로 동작하였다. 즉 and 가 아닌 or 처럼 연산되는 문제점을 발견한것이다.

보다 정확한 쿼리를 확인하기 위해 p6spy 라이브러리를 통해서 DB에 나가는 쿼리를 확인해 보았다.

그 결과 나의 예상과 전혀 다른 쿼리가 나갔다.

SELECT CASE WHEN EXISTS (
    SELECT 1
    FROM expense_document
    WHERE expense_document_id IN (1,2,3)
    HAVING COUNT(DISTINCT expense_document_id) = 3
) THEN 'Yes' ELSE 'No' END AS result;
select
        e1_0.expense_document_id      
    from
        expense_document e1_0      
    where
        e1_0.expense_document_id in (1,2,3) fetch first 1 rows only

고치는 법 결과

결론부터 말하면 못 고친다. 관련 내용을 계속하여 구글링하고 공식 문서를 들여다 보았으나 해당 내용을 찾지 못하였다. 그리하며 data jpa 프로젝트 레포지토리에 직접 이슈를 달았고 답변을 받았다.

답변 내용

exists관련해서 메서드 이름으로 data jpa가 쿼리를 생성해주는 것은 exists하나인듯 하다. 그러므로 처음부터 제공하지 않는 기능이다.

만약 내가 원하는 기능을 사용하려면 @Query로 jpql을 작성하여 코드를 작성하거나 혹은 QueryDsl로 쿼리를 생성해야 한다.

추가

내가 지금 원하는 로직은 비즈니스 로직상 종종 필요한 기능이라고 생각한다.

얼마전 동아리(GDSC)를 성공적으로 끝내면서 다른 사람의 회고를 보았다. 그 사람은 오픈소스 컨트리뷰션을 하였고 너무 어렵게만 접근하지 않았으면 좋겠다고 하였다. 그렇기에 나도 이번에 어려움을 겪은 문제를 직접 컨트리뷰션을 해 볼 생각이다. 잘 될지는 모르겠지만 컨트리뷰션에 성공을 하든 실패를 하든 그 과정에서 분명 내가 얻는 것이 있을것이다.