[JPA]검색 시 hibernate 에러와 해결

백승호·2022년 6월 8일
1

문제 상황

검색 기능을 구현하기 위해 JPA에서 제공하는 containing을 사용하기로 했습니다.
JPA 공식문서에서 나온 것 대로 containing과 or 연산자를 이용해서 총 post 칼럼의 postTitle, location, theme를 기준으로 검색하는 코드를 작성했습니다.

PostRepository 검색 JPA

분명 이렇게 작성하는 것은 맞는데... 딱 봐도 너무 길고 이상하다 느껴지긴 합니다..

그런데 문제는 이것 뿐만이 아니었습니다. 포스트맨으로 테스트를 맨 처음 시도할 때는 결과가 잘 나왔습니다. 그런데 반복적으로 검색하는 테스트를 할려고 하자 이런 문구와 함께 400 에러가 발생했습니다.

코드에는 아무 이상이 없어서 포스트맨의 문제인가 싶다가도 맨 처음 실행할 때는 결과가 잘 나오는것이 의문이 들어서 구글링을 시작했습니다..!

그때 찾은 이슈 하나가 있었습니다..

hibernate 버전에 따른 like 쿼리 fail 에러

CriteriaQuery with Like predicate fails when repeated with java.lang.IllegalArgumentException: Parameter value [] did not match expected type [java.lang.String (n/a)]

[설명]
The call to entityManager.createQuery(criteriaQuery) fails when executed more then once for a CriteriaQuery containing a Like-predicate with a pattern parameter and an escape character literal. With an escape character parameter the problem does not exist.

이렇게 언급이 되어 있습니다. 한 번 이상 파라미터와 이스케이프 캐릭터를 포함한 like 쿼리문을 날렸을 때 에러가 발생한다는 것이었습니다. 엥, escape..?
파라미터는 넣었지만 escape는 따로 작성하지 않아서 혹시나 싶은 마음에 hibernate.show-sql을 설정해 sql문을 확인해봤습니다.

hibernate 확인 결과


??.. 정말 제 머릿속에도 물음표가 가득해졌습니다.. 저는 escape를 사용하지 않았지만 알 수 없는 이유로 escape 캐릭터가 삽입이 됐고, hibernate는 그것을 이상하게 해석하여 포스트맨 에러와 같이 paramter value를 [\] 라고 인식하는 것 같았습니다.

JPA 공식 github의 입장

<우리도 잘 모르겠지만 버전 문제니까 다음번에 고쳐줄게>
hibernate 5.6.5 버전 이상 부터 현재까지 like쿼리 시 이런 문제가 있다고 합니다.
현재 제가 사용중인 hibernate 버전은 5.6.8 버전으로 아직 문제가 해결이 안 된 것으로 판단했습니다. 이에 대한 해결책으로는 버전을 5.6.5 이하로 낮추거나 쿼리문을 작성하는 것이 있다고 생각했습니다.

hibernate 버전을 낮추면 추가적으로 발생할 다른 문제들이 걱정 되기도 했고, 이번 기회에 JPQL을 활용한 쿼리를 적용시켜보고 싶어서 후자의 방법을 택했습니다.

해결

다음과 같이 @Query 어노테이션과 함께 JPQL을 적용시켜 해결했습니다.
JPQL에 대해 짧게 언급을 하면 SQL과 다르게 테이블을 기준으로 쿼리를 짜는것이 아니라 엔티티(객체)를 기준으로 쿼리를 짜서 자바 친화적으로 구현할 수 있게 해준 것입니다.
SQL과 문법도 유사하여 native query와의 차이는 단지 nativeQuery=true 또는 false(JPQL)로 인지해도 된다고 합니다.

쿼리 구현

물론 메소드명은 바꿔도 됐지만, 저렇게 JPA를 활용하면 에러가 난다는 것을 기억하기 위해 우선 남겨뒀습니다.
Post를 p로 alias처리하고 like쿼리와 마찬가지로 %~% 안에 ':p.파라미터' 형식으로 대입했습니다.
물론 escape 캐릭터는 작성하지 않았습니다^^

이렇게 문제가 해결됐습니다!

참고

https://jforj.tistory.com/90

https://github.com/spring-projects/spring-data-jpa/issues/2472

https://stackoverflow.com/questions/71642208/parameter-value-gabrek-did-not-match-expected-type-java-lang-character-n-a (stack overflow)

https://hibernate.atlassian.net/browse/HHH-15142

profile
처음처럼

0개의 댓글