2013-07-11 5 views
1

나는 하나의 부모/자식 @OneToMany을 가지고 있는데 컬렉션은 Set (중복 없음)입니다. 서버의 Parent에서 자식에 액세스하려고하면 아래 오류가 발생합니다.최대 절전 모드 너무 게으름

request.setAttribute을 통해 클라이언트 측에 Parent를 전달하고 JSTL을 사용하여 Parent에 액세스하면 Child 객체 멤버에 직접 액세스 할 수 있습니다. 학부모/자녀에게는 게터/세터가 있습니다. 내가 톰캣 6.0.32, 봄 3.1.0, JDK6 사용하고

, 어린이

@Entity 
@Table(name="SUSER") 
public class SUser { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private int su_id; 

    @Column(name="displayname", nullable=true, 
    columnDefinition="varchar", length=50, insertable=true, updatable=true) 
    private String displayname; 

    @Column(name="last_activity", nullable=true, columnDefinition="datetime", 
    insertable=true, updatable=true) 
    private String last_activity; 

    @Column(name="ldapuser", nullable=true, columnDefinition="varchar", 
    length=50, insertable=true, updatable=true) 
    private String ldapuser; 

    @OneToMany 
    @org.hibernate.annotations.IndexColumn(name="SU_ID") 
    @JoinColumn(name="su_id", insertable=true, updatable=true) 
    private Set<SUserAttributes> suattr = new HashSet<SUserAttributes>(); 

상위 3

최대 절전 모드

@Entity 
@Table(name="SUSER_ATTRIBUTES") 
public class SUserAttributes { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private int sua_id; 

    @Column(name="su_id") 
    private int su_id; 

    @Column(name="sua_key", nullable=true, columnDefinition="varchar", 
    length=64, insertable=true, updatable=true) 
    private String sua_key; 

    @Column(name="sua_value", nullable=true, columnDefinition="varchar", 
    length=128, insertable=true, updatable=true) 
    private String sua_value; 

DAO

,451,515,
package com.oasis.implementation.dao; 

import java.util.LinkedList; 
import java.util.List; 

import org.apache.log4j.Logger; 
import org.hibernate.SQLQuery; 
import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.hibernate.criterion.Restrictions; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 

import com.oasis.implementation.ClientInfo; 
import com.oasis.implementation.SUser; 

public class SUserDaoImpl implements SUserDao { 

    @SuppressWarnings("unused") 
    private static Logger logger = Logger 
      .getLogger(ClientDownloadsDaoImpl.class); 

    @Autowired 
    @Qualifier("implementationSessionFactory") 
    private SessionFactory sessionFactory; 

    @SuppressWarnings("unchecked") 
    @Override 
    public List<SUser> getAllSUsers(){ 
     List<SUser> suList = null; 
     Session session = null; 

     try 
     { 
      session = sessionFactory.openSession(); 
      session.beginTransaction(); 
      suList = session.createQuery("from SUser").list();   
      session.getTransaction().commit(); 
     } 
     catch (RuntimeException e) 
     {   
      System.out.println (e.getMessage()); 
     } 
     finally 
     { 
      if (session != null) 
      {   
       session.close(); 
      } 
     }  

     return suList;  

    } 

    @Override 
    public List<SUser> getSUserById(int su_id) { 
     Session session = null; 
     SUser sUser = null; 
     LinkedList<SUser> suList = new LinkedList<SUser>(); 

     try { 
      session = sessionFactory.openSession(); 
      session.beginTransaction(); 
      sUser = (SUser) session.get(SUser.class, su_id); 
      suList.add(sUser); 
      session.getTransaction().commit(); 
     } catch (RuntimeException e) { 
      System.out.println(e.getMessage()); 
     } finally { 
      if (session != null) { 
       session.close(); 
      } 
     } 

     return suList; 
    } 

    @Override 
    public List<SUser> getUserByLdap(String ldapuser){ 
     Session session = null; 
     int user_id = 0; 
     List<SUser> suList = null; 

     try 
     { 
      session = sessionFactory.openSession(); 
      session.beginTransaction(); 

      SQLQuery sqlq = session.createSQLQuery("select su_id from 
      suser where ldapuser = '" + ldapuser + "'"); 
      user_id = (Integer)sqlq.uniqueResult(); 
      suList = getSUserById(user_id); 

      session.getTransaction().commit(); 
     } 
     catch (RuntimeException e) 
     {   
      System.out.println (e.getMessage()); 
     } 
     finally 
     { 
      if (session != null) 
      {   
       session.close(); 
      } 
     }  

     return suList;  

    } 
} 

오류 메시지

Hibernate: select suser0_.su_id as su1_11_0_, suser0_.displayname as 
displayn2_11_0_, suser0_.last_activity as last3_11_0_, suser0_.ldapuser as l 
    dapuser11_0_ from SUSER suser0_ where suser0_.su_id=? 
    ERROR - failed to lazily initialize a collection of role: com.oasis.implementation.SUser.suattr, no session or session was closed 
    org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.oasis.implementation.SUser.suattr, no session or 
    session was closed 
      at 

답변

3

이 오류는 당신이 (즉 컬렉션이 아직 DB에서 정말 인출되지 않았 음을 의미)가 느리게로드 모음에 액세스를 시도하고 있기 때문에 무슨 일이 일어나고 최대 절전 모드 번 세션이 닫혔습니다. 그래서, 아이들에게 가져 오기 위해 DB로 돌아갈 방법이 없습니다. 당신도 할 수 :

  • 포스 부하 Hibernate.initialize(parent.getSuattr());

  • 에 대한 호출로 Session이 아직 열려 협회가 명시 적 join fetch 문에 그 사용 사례에 대한 특정 쿼리를 만듭니다.

  • 부모에게 쿼리 할 때 항상 자식을 쿼리하려는 경우 매핑을 수정하여 열성적으로 가져옵니다.

  • OpenSessionInView 패턴을 사용하십시오. 이 패턴은 요청이 처리 되려고 할 때 (보통 Filter) Hibernate 세션을 열고, 완전히 처리 될 때까지 계속 열어 둔다. 이 접근법은 현재 디자인에 적합하지 않을 수 있으며 (재 설계가 필요함) 조심스럽게 사용해야합니다. 실제 상황을 망칠 수있는 몇 가지 함정이 있으므로주의 깊게 사용해야합니다.

+0

EAGER 가져 오기 접근 방식을 사용했습니다. – user931501

+0

답변을 수락 할 수 없습니다. 좋아요/싫어요 아이콘이 없습니다. – user931501

+0

get (Object.class, id) 메서드를 사용하여 객체를 가져 오는 것이 객체를 가져 오지는 않지만 객체에 대한 참조 (proxy)를 얻는 것을 이해합니다.Hibernate가 객체를 얻으려면, 서버 측에서 객체의 다른 데이터 멤버에 액세스해야한다. 나는 서버 측에서 이것을 시도했지만 객체를 얻지 못했습니다. ???? – user931501

0

코드의 가장 큰 문제점은 세션/트랜잭션을 열고 DAO 찾기 메소드에서 닫기/커밋한다는 것입니다.

트랜잭션 (따라서 최대 절전 세션)은 작업 단위 범위에 대해 열려 있어야합니다. 예를 들어, 트랜잭션은 애플리케이션 서비스 메소드 호출 전후에 열리거나 커밋되어야하므로 해당 애플리케이션 서비스 메소드에서 수행 된 모든 작업은 모두 하나의 트랜잭션으로 수행됩니다. (OpenSessionInView는 비슷한 근거를 공유합니다.이 경우에는 "작업 단 위"가 더 길어집니다)

+0

EAGER 가져 오기를 @OneToMany와 그 작업에 추가했습니다. – user931501

+1

이유가 무엇인지 알아야합니다. EAGER를 추가하면 일부 사례를 해결할 수 있지만 현재 접근법을 계속 사용하면 근본적인 아키텍처 설계 결함이므로 더 많은 문제에 직면하게됩니다. –

+0

어쨌든 거래는 finder method에서 "is"입니다. 열린 세션> 데이터 가져 오기> 세션 닫기 만 있으면됩니다. – user931501