달력

42024  이전 다음

  • 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

하이버네이트 보던 도중.. 이런 에러 발생..

정확한 에러는

net.sf.hibernate.LazyInitializationException: Failed to lazily initialize a collection - no session or session was closed
 at net.sf.hibernate.collection.PersistentCollection.initialize(PersistentCollection.java:209)
 at net.sf.hibernate.collection.PersistentCollection.read(PersistentCollection.java:71)
 at net.sf.hibernate.collection.Set.size(Set.java:106)

.

.

.

 

머 대충 이런 메세지다.

 

이 에러가 발생하는 원인은.. mapping 설정 중에 lazy="true" 부분이 있다.

하이버네이트 설명중에 lazy="true" 일 경우.. 객체를 뒤늦게 초기화 한다(?) 라고 하는데..

이게 쿼리는 이미 만들어져있지만 실제 데이터를 꺼내와서 객체에 담는 작업을 나중에 한다는 말인지.. 잘 모르겠다 ㅡ,.ㅡ 

 

예상이지만 하이버네이트의 PersistenceCollection 의 동작방식이 열쇠를 쥐고 있을 것 같다.

 

지금 연습삼아 만들어보는 게시판의 클래스와 Mapping 정보를 보면 이렇다.

   /**
    * @hibernate.set
    *  table="board_file"
    *  lazy="true"
    *  inverse="false"
    *  order-by="idx"
    *  cascade="all"
    *
    * @hibernate.collection-key
    *  column = "parent"
    * @hibernate.collection-one-to-many
    *  class = "com.javarush.board.dto.AttatchFile"
    */
    public Set getAttatchFile() {
        return articleFile;
    }

    public void setAttatchFile(Set attatchFile) {
        this.attatchFile= attatchFile;
    }

 

hbm.xml 파일로 번역되면 아래와 같이 된다.

 

        <set
            name="attatchFile"
            table="board_file"
            lazy="true"
            inverse="false"
            cascade="all"
            sort="unsorted"
            order-by="idx"
        >

              <key
                  column="parent"
              >
              </key>

              <one-to-many
                  class="com.javarush.board.dto.AttatchFile"
              />

        </set>

 

하나의 게시물을 읽어올때... 게시물 고유번호에 대한 자식들(Upload) 을 같이 가져와야 하는데..

이 매핑 정보를 통해 별도의 쿼리 없이 Upload 정보를 담고있는 객체들이 Set 에 입력되어서

게시물 Bean 에 담겨서 반납된다..

 

문제는... lazy="true" 일때.. 하이버네이트 세션이 닫혀있으면.. 객체정보를 가져오지 못한댄다 ㅡㅡ

 

그래서... 세션이 닫히기 전에 객체를 초기화 시켜줘야 했다.

초기화 방법은 간단..

 

Session ss = factory.openSession();

bean = mgr.read(new Integer(게시물고유번호));

 

// Set 의 size() 를 호출하여 객체를 초기화(객체로딩???)시킨다.

bean.getAttatchFile().size(); <-- 요기서 명시적으로 객체를 로딩하는것 같다.

 

ss.close();

 

Iterator iter = bean.getAttatchFile().iterate();

 

while(iter.hasNext()){

  Object = iter.next();

}

 

이렇게 해서 세션이 닫히기 전에 객체들을 가져왔다.

 

만약 위에 코드가 아래처럼 되어있으면 영락없이 LazyInitializationException 가 던져진다

Session ss = factory.openSession();

bean = mgr.read(new Integer(게시물고유번호));

ss.close();

// 세션이 닫힌 상태기 때문에 아래쪽으로는 LazyInitializationException  가 발생한다 ;;

Iterator iter = bean.getAttatchFile().iterate();

 

while(iter.hasNext()){

  Object = iter.next();

}

 

Posted by tornado
|