Spring Data JPA Interface Projection 시 InaccessibleObjectException이 발생하는 경우

메밀·2024년 5월 23일
post-thumbnail

⭐️ 결론부터!

Interface Projection이 Proxy 객체를 반환하기 때문에 나는 오류
DTO Projection으로 바꿔서 Proxy 객체가 안 넘어오도록 하면 해결 가능

🧐 InaccessibleObjectException

😞 오류 로그

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.data.keyvalue.core.UncategorizedKeyValueException: Unable to make field protected java.lang.reflect.InvocationHandler java.lang.reflect.Proxy.h accessible: module java.base does not "opens java.lang.reflect" to unnamed module @2b9da33d] with root cause

java.lang.reflect.InaccessibleObjectException: Unable to make field protected java.lang.reflect.InvocationHandler java.lang.reflect.Proxy.h accessible: module java.base does not "opens java.lang.reflect" to unnamed module @2b9da33d

🔭 발생 지점

List<Username> usernames = gardenerRepository.findByProviderIsNullAndEmail(email);

인터페이스 프로젝션 메소드를 사용한 부분이다.

🔍 해석

java.base 모듈이 java.lang.reflect 패키지를 열어주지 않아서 Proxy 클래스의 내부 필드에 접근할 수 없는 문제

Java 9 이상에서 발생

🥳 해결 방법

해결 방법은 간단하다.

  • reflect 패키지에 접근 가능하도록 설정을 변경하거나,
  • 아예 Proxy 객체가 넘어가지 않도록 하면 된다.

내 경우 꼭 Proxy를 써야 하는 상황도 아니라 설정을 바꿀 이유가 없으므로 DTO Projection으로 변경하여 해결하였다.

👉 덧붙여

Interface Projection을 사용하고 있다면, ClassCastException, LazyInitializationException 또한 프록시 객체 때문에 일어나는 경우가 많다.

이 경우의 해결책도 다음과 같다.

  • Proxy 객체를 원본 객체로 바꾸기
    • initialize()를 사용하든 DTO로 다시 매핑을 하든...
  • Proxy 객체가 안 넘어오게 아예 DTO Projection 하기

나의 경우 필요한 것만 딱 받아와서 바로 사용하려고 프로젝션을 하는데 첫번째 해결책은 비효율적으로 느껴져 사용하지 않았다.

0개의 댓글