본문 바로가기
TroubleShooting/Sketcher

TroubleShooting - 1 (@Transactional)

by 완두완두콩 2022. 1. 31.

 

 

문제 발생


org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: sketcher.scheduling.domain.User.managerHopeTimes, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:606)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585)
at org.hibernate.collection.internal.AbstractPersistentCollection.write(AbstractPersistentCollection.java:409)
at org.hibernate.collection.internal.PersistentBag.add(PersistentBag.java:407)

 

테스트 케이스를 작성해 보던 중 , 위와 같은 오류가 발생했다.

Session 이 없다는 부분을 봐서는 아무래도 DB 에 저장될 때 오류가 생기는 것 같았다.

 

원인 추론


매니저만 저장할 때는 문제 없이 DB 에 저장 완료

하지만 매니저와 스케줄을 같이 저장할 때는 오류가 발생했다.

user 와 HopeTime 은 연관관계 매핑으로 이어져 있고 , 다음과 같이 fetch 전략이 LAZY 로 설정돼있었다.

스케줄을 저장하기 위해서는 반드시 user 에 대한 정보를 넣어야 하는데 아마도 위에서 저장된 user에 대한 정보가

session 에 없어서 HopeTime 에 저장이 되지 않는 것 같았다.

 

해결


@Transacitonal 어노테이션을 사용함으로써 해결하였다.

 

우선 , user 에서 save 하는 경우와 HopeTime 에서 save 하는 경우는 각각 다른 영속성 컨텍스트 세션으로 동작한다.

그 이유는 각각의 service 단이 다르기 때문이다.

그렇기 때문에 내가 user 에서 save 한 뒤 , HopeTime 에 저장하려는 경우 , 다른 영속성 컨텍스트 세션이기때문에

값을 불러오지를 못했던 것이다.

 

방법 1

이를 해결하기 위해서 하나의 트랜잭션으로 묶어야 겠다고 생각했다.

-> 메소드단에 @Transactional 어노테이션을 붙임으로써 해결.

 

방법 2 :

-> fetch 조인을 LAZY 가 아닌 EAGER 로 변경한다.

EAGER (즉시조인)은 말 그대로 연관된 엔티티를 조회하지 않아도 모든 정보를 즉시 조회하고 

LAZY(지연조인) 은 연관된 엔티티를 조회할 때 조회 쿼리를 날리게 된다.

하지만 EAGER 는 성능 문제가 발생할 수 있다.

 

상황에 따라 알맞은 방법을 쓰는게 필요하다.

 

댓글