ENAN

Developer, Artist, Traveler

공부/Spring

failed to lazily initialize a collection of role 에러

ENAN 2021. 1. 7. 01:57

사용자의 역할 정보(roles)를 아래와 같이 다대다 관계로 설정해주는 중, lazyInitializationException 예외를 만났다.

data class User(
	    . . .
        @ManyToMany(cascade = [CascadeType.ALL])
        @JoinTable(name = "user_roles", joinColumns = [JoinColumn(name = "user_id")], inverseJoinColumns = [JoinColumn(name = "role_id")])
        var roles: MutableSet<Role> = mutableSetOf(),
        . . .

아래는 에러 메세지이다.

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:
com.enan.Domain.User.roles, could not initialize proxy - no Session

 

지연 로딩으로 생성된 프록시를 초기화하는 것(즉, 연관된 데이터를 가져오는 것)이 불가능한 상황이 되었다는 말이다.

원인은 조회 결과가 반환 되면서 트랜잭션이 이미 종료된 이후에 연관된 데이터에 접근하려 했기 때문이다.

(아마 나의 경우는 user 정보를 받아온 후에 roles가 프록시만 남아있는 상태에서 security에서 role을 확인하려 해서 오류가 났을 것)

 

해결 방법은 @ManyToMany 등 관계 설정 어노테이션에 (fetch = FetchType.Eager) 설정을 추가해주는 것이다.

data class User(
	    . . .
        @ManyToMany(cascade = [CascadeType.ALL], fetch = FetchType.EAGER)
        @JoinTable(name = "user_roles", joinColumns = [JoinColumn(name = "user_id")], inverseJoinColumns = [JoinColumn(name = "role_id")])
        var roles: MutableSet<Role> = mutableSetOf(),
        . . .

이를 즉시 로딩이라고 하는데, 데이터를 가져올 때 조인을 사용해서 연관된 데이터를 한번에 가져오는 방식이다.

지연 로딩은 그 반대로, 데이터를 가져올 때 프록시라는 가짜 엔티티를 사용해 필요한 데이터만 가져오고, 연관된 데이터를 사용하려 하는 시점에 다시 데이터를 가져와 사용하는 방식이다.

 

즉시 로딩/지연 로딩에 대한 내용이 이렇게 짧게 설명할 내용은 아니지만, 글의 주제에서 벗어나는 것 같아서 내가 읽고 이해했던 글을 링크로 남겨 설명을 대신한다. (바로 앞글에 프록시에 대한 설명도 있으니 같이 읽어보는 것을 추천!)

logical-code.tistory.com/140

 

[JPA] 즉시 로딩/지연 로딩

앞선 포스팅에서 프록시에 대해 알아보았습니다. 이번 포스팅에서는 JPA에서 프록시를 어떻게 활용하는지, 즉시 로딩과 지연 로딩을 통해 알아봅니다. 지연 로딩 (Lazy Loading) 1 2 3 4 5 6 7 8 9 @Entity p

logical-code.tistory.com

 

'공부 > Spring' 카테고리의 다른 글

Kotlin Spring에서의 @Autowired annotation  (0) 2021.01.07
Github Action 빌드시 contextLoads Failed 오류  (2) 2020.11.20