티스토리 뷰

* 개요 

- 단순히 리스트 불러오는 하이버네이트 이용한 메서드가 몇 번 실행 후 무한루프를 돌며 실행되지 않는 현상이 발생했다.

- 열어놨던 세션을 닫지 않아 누적되면서 생기는 문제였음.




* 멈췄던 이유 


- 내가 사용하는 메서드 구조는 항상 이런식이었음.

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

오류발생


참고 : http://stackoverflow.com/questions/4961636/no-hibernate-session-bound-to-thread-and-configuration-does-not-allow-creation




* 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);

}

}


- 참고 :  http://yayongi.tistory.com/entry/%ED%95%98%EC%9D%B4%EB%B2%84%EB%84%A4%EC%9D%B4%ED%8A%B8-%EC%82%AC%EC%9A%A9%EB%B2%95


- 참고 : 원본에서는 SessionFactory를 직접 가져오는 코드를 활용하지만, 내 프로그램에서는 하이버네이트 설정 파일이 여러개라 설정이 번거러워 파라메터로 넘겨줘서 사용하고 있음.


- HibernateUtil.getCurrentSession(DAO.getSessionFactory());





* 굳이 HibernateUtil 을 따로 선언 해서 사용하는 이유?


- getSession() (또는 openSession() ) 후에 꼬박꼬박 close() 하는 코드를 작성해서 사용하면 무방할 듯 하지만,

- 세션을 닫아버리면, 이후 다른 부분에서 FetchType.LAZY 선언된 속성을 이용할때 다음 오류 발생함.

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

- close() 안 하고 메서드를 종료시키면 문제 없지만  닫히지 않은 세션이 누적되면서 문제 발생

- 따라서 세션 관리하는 클래스를 따로 만들어서 사용.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함