[Spring JPA🌿] fetch join + 지연로딩 관련 에러 해결
해결 과정에서 같이 만났던 오류/에러들
- Large Objects may not be used in auto-commit mode
- MultipleBagFetchException
- failed to lazily initialize a collection of role
상황 설명 및 해결
1) Large Objects may not be used in auto-commit mode
게시글의 본문에 대해서 @Lob 어노테이션을 붙여서 코드를 짰다. 이후 코드를 실행했을 때 DB에서 oid 타입으로 값이 저장된 것을 확인할 수 있었다.
데이터 타입을 text로 변경하기 위해서 어노테이션을 다음과 같이 수정했다.
@Column(nullable = false, columnDefinition = "text")
private String content;
사실 이 문제는 제목과는 크게 관련이 없을 수도 있는데, 문제를 해결하는 과정에서 같이 만났던 문제였기 때문에 같이 기록한다.
2) MultipleBagFetchException
엔티티와 연관된 모든 정보를 가져와야 하는 부분을 짜다가 LazyInitializationException 에러가 났다. JPA N+1문제도 같이 해결하기 위해서 Fetch Join을 사용하는 것으로 코드를 변경했다.
@Query("SELECT DISTINCT p FROM Post p " +
"LEFT JOIN FETCH p.images " +
"LEFT JOIN FETCH p.postHashtags " +
"ORDER BY p.createDate DESC")
List<Post> findAllPost();
위와 같이 코드를 짰는데 MultipleBagFetchException이 발생했다.
찾아보니 Fetch Join은 ToMany 1개만 가능하다고 한다. 해결하기 위해 쿼리를 나눠서 하거나 배치 사이즈를 설정하는 방법이 있다. 나는 이미 배치 사이즈를 설정해둔 상태였기 때문에 아래처럼 쿼리를 쪼개서 해결했다.
@Query("SELECT p FROM Post p JOIN FETCH p.images WHERE p.id = :postId")
Post findPostWithImagesById(@Param("postId") Long postId);
@Query("SELECT p FROM Post p JOIN FETCH p.postHashtags WHERE p.id = :postId")
Post findPostWithPostHashtagsById(@Param("postId") Long postId);
@Query("SELECT p FROM Post p")
List<Post> findAllPostWithImagesAndPostHashtags();
3) failed to lazily initialize a collection of role
JPA에서 지연로딩을 하기 위해서는 항상 영속성 컨텍스트가 있어야 하는데, 트랙잭션 밖에서 조회를 시도해서 발생한 문제라고 한다. 그래서 관련된 모든 메소드에 @Transactional 어노테이션을 추가해서 해결했다.
도움 받은 링크들
https://winter1396love.tistory.com/68
https://jojoldu.tistory.com/457
https://pasudo123.tistory.com/473