티스토리 뷰
* 개요
- 단순히 리스트 불러오는 하이버네이트 이용한 메서드가 몇 번 실행 후 무한루프를 돌며 실행되지 않는 현상이 발생했다.
- 열어놨던 세션을 닫지 않아 누적되면서 생기는 문제였음.
* 멈췄던 이유
- 내가 사용하는 메서드 구조는 항상 이런식이었음.
Session s = this.session(); // this 는 HibernateDaoSupport 를 상속받음.
// .. 쿼리 호출 내용
s.close();
- 멈추던 메서드는, 메서드#1에서 세션 여닫는 내용 있는 메서드#2를 호출하는 구조 였음. 둘다 세션 여닫는 내용이 있으므로 결과적으로 다음과 같은 코드가 됨.
Session s1 = this.getSession();
Session s2 = this.getSession();
// ... s2 이용하는 코드
s2.close();
// ... s1 이용하는 코드
s1.close();
- 중복으로 session을 가져오는게 문제였나 싶었는데 자세히 살펴보니
Session s1 = this.getSession();
Session s2 = this.getSession();
getSession().사용하는 코드 // 즉, s3 를 생성함.
s2.close();
// ... s1 이용하는 코드
s1.close();
- 이런 형태로 되어 있었음... 즉 2번째 세션은 활용하지 않고, 3번째 세션 생성한 후 닫지 않는 코드
- 이 코드를 반복하다 보면 닫히지 않은 세션이 늘어나게 되고, 결과적으로 세션이 닫히기를 계속해서 기다리느라 실행이 안된 것.
[ Hibernate session 가져오는 방법 정리 ]
* getSessionFactory().openSession()
언제나 새로운 세션을 연다. 따라서 마치면 항상 close() 실행해줘야 한다.
* getSessionFactory().getCurrentSession()
- 트랜잭션 적용되어야 오류가 발생하지 않는다.
- 즉 @Transactional 선언하거나, Session#beginTransaction() 실행이 되어야 사용 가능
- 설정파일에 설정이 안됐다면
org.hibernate.HibernateException: No Hibernate Session bound to thread, ...
오류 발생
- beginTransaction() 호출되지 않았다면
org.hibernate.HibernateException: createQuery is not valid without active transaction
오류발생
* hibernateDaoSupport.getSession()
openSession 과 다를 바 없어보임..
즉 매번 close() 실행해야 함.
* HibernateUtil 선언
- ThreadLocal 이용해서 쓰레드 별로 세션 할당해주는 유틸 작성해서 사용가능하다.
- 매번 새로운 세션 생성이 아니라 없을때만 생성하고,
- 이미 생성되어있다면 계속 보관하면서 사용
public class HibernateUtil{
public static final ThreadLocal session = new ThreadLocal();
public static Session getCurrentSession(SessionFactory sessionFactory) throws HibernateException{
Session s = (Session)session.get();
if(s == null){
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
public static void closeSession() throws HibernateException{
Session s= (Session)session.get();
if(s != null)
s.close();
session.set(null);
}
}
- 참고 : 원본에서는 SessionFactory를 직접 가져오는 코드를 활용하지만, 내 프로그램에서는 하이버네이트 설정 파일이 여러개라 설정이 번거러워 파라메터로 넘겨줘서 사용하고 있음.
- HibernateUtil.getCurrentSession(DAO.getSessionFactory());
* 굳이 HibernateUtil 을 따로 선언 해서 사용하는 이유?
- getSession() (또는 openSession() ) 후에 꼬박꼬박 close() 하는 코드를 작성해서 사용하면 무방할 듯 하지만,
- 세션을 닫아버리면, 이후 다른 부분에서 FetchType.LAZY 선언된 속성을 이용할때 다음 오류 발생함.
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
- close() 안 하고 메서드를 종료시키면 문제 없지만 닫히지 않은 세션이 누적되면서 문제 발생
- 따라서 세션 관리하는 클래스를 따로 만들어서 사용.
'SW개발 > Spring Framework' 카테고리의 다른 글
Hibernate /Not all named parameters have been set (0) | 2017.10.31 |
---|---|
hibernate SQL Error: 1064, SQLState: 42000 (0) | 2017.05.31 |
Eclipse Spring MVC 프로젝트에 Hibernate 적용 (0) | 2017.05.19 |
Eclipse Spring MVC Project 시작 (0) | 2017.05.15 |
Spring Junit Test 환경 구성 (1) | 2017.02.13 |