게 으 름 로드 이상 처리

오늘 은 하 이 버 네 이 트 의 게 으 름 로드 이상 과 1 + N 문 제 를 이야기 합 니 다.이 두 가 지 는 자바 면접 에서 꼭 물 어 봐 야 할 문제 입 니 다. 자, 쓸데없는 소리 하지 말고 이 두 가지 문 제 를 봅 시다.
게 으 른 로드 란 무엇 입 니까?답: Hibernate 프레임 워 크 에서 우리 가 방문 할 데이터 의 양 이 너무 많 을 때 캐 시 를 사용 하 는 것 이 적당 하지 않 습 니 다. 메모리 용량 이 제한 되 어 있 기 때문에 병발 량 을 줄 이 고 시스템 자원 의 소 모 를 줄 이기 위해 Hibernate 는 게 으 른 로 딩 체제 로 이러한 결함 을 보완 하지만 이것 은 게 으 른 로 딩 의 전체적인 성능 을 향상 시 키 는 것 이 아 닙 니 다.우리 가 말 하 는 게 으 른 로 딩 도 지연 로 불 린 다. 검색 할 때 바로 데이터 베 이 스 를 방문 하지 않 고 대리 대상 으로 돌아 가 대상 을 진정 으로 사용 할 때 만 데이터 베 이 스 를 방문 할 수 있다.
게 으 름 로드 의 역할: 성능 최적화: 분류: 1. 게 으 름 로드 2, 집합 게 으 름 로드 3, 단일 엔 드 와 관련 된 게 으 름 로드 (다 대 1)
![       ](http://img.blog.csdn.net/20151213155704143)        

게 으 른 로 딩 1, 클래스 의 게 으 른 로 딩 1, session. load 방법 을 이용 하여 대리 대상 2 를 생 성 할 수 있 습 니 다. session. load 방법 을 실행 할 때 sql 문 구 를 보 내지 않 습 니 다. 3. 일반 속성 을 얻 을 때 sql 문 구 를 보 냅 니 다. 4. 일반 속성 만 유효 합 니 다. 표시 문자 속성 에 대해 효과 가 없 는 5. 기본 적 인 상황 은 게 으 른 로 딩 2 입 니 다.집합 게 으 른 로 딩 false 는 session. get 일 때 집합 을 불 러 옵 니 다. true 는 집합 을 옮 겨 다 닐 때 만 extra 를 불 러 옵 니 다. 집합 에 대해 count, min, max, sum 등 작업 3, 단일 엔 드 와 관련 된 게 으 른 로 딩 (다 대 1) 을 합 니 다.
<class name="com.test.Student"table="student" lazy="true">  
         
<class name="com.test.Student"table="student" proxy="com.test.Student">  

게 으 른 로드 이상:
하 이 버 네 이 트 프레임 워 크 의 역할 은 코드 와 데이터 베 이 스 를 대상 을 대상 으로 하 는 존재 방식 으로 연결 시 키 는 것 이다. 데이터 베 이 스 를 통 해 데 이 터 를 추출 하고 하 이 버 네 이 트 를 통 해 메모리 의 대상 A 로 전환 하 는 것 이다. 우 리 는 대상 의 구성원 도 다른 유형의 인 스 턴 스 (다른 유형의 대상 B) 일 수 있다 는 것 을 알 고 있다. 이 구성원 의 대상 B 는 데이터 베이스 에서 도 자신 이 대응 하 는 데 이 터 를 가지 고 있다.많은 경우 에 우리 가 꺼 낸 대상 A 는 B 대상 이 업 무 를 할 필요 가 없다. 만약 에 모두 꺼 내 면 성능 의 낭 비 를 초래 할 수 있다. 그래서 개발 과정 에서 우 리 는 A 대상 의 적재, 즉 데이터 베이스 에서 데 이 터 를 추출 하고 A 대상 으로 전환 하 는 과정 을 게 으 른 로드 로 정의 한다. 말 그대로게 으 름 은 데 이 터 를 가 져 올 때 멤버 대상 B 에 해당 하 는 데 이 터 를 가 져 오지 않 는 다 는 뜻 이다.B 가 필요 할 때 데이터베이스 에서 대상 을 찾 습 니 다.또한 데이터베이스 에서 데 이 터 를 가 져 오 는 것 은 session 을 통 해 가 져 온 것 임 을 알 아야 합 니 다. 프로그램 이 B 대상 을 불 러 오 려 고 할 때 session 이 닫 히 거나 기한 이 지나 면 게 으 른 로 딩 이상 이 발생 할 수 있 습 니 다.
게 으 른 로드 이상 해결 방안:
인터넷 에서 찾 는 해결 방안 은 참고 만 제공 하고 사고방식 은 정확 하 다
1. 게 으 름 로드: lazy = "false" 를 직접 적용 하지 않 습 니 다. 이것 은 상당히 일반적인 방법 입 니 다 (그러나 실제 개발 에 서 는 일반적으로 바람 직 하지 않 습 니 다). 게 으 름 로드 가 필요 하 다 면 문 제 를 해결 할 수 없습니다.
2. OpenSessionInViewFilter 나 OpenSessionInViewInterceptor 는 이름 에서 보 듯 이 view 층 에서 dao 층 을 호출 하 는 게 으 른 로드 문 제 를 해결 하 는 방법 입 니 다.웹 request 에 단일 한 hibenate session 을 제공 하 는 것 이 목적 이지 만 웹 request 에 만 hibenate session 을 제공 할 수 있 습 니 다.지정 한 웹 request 를 모두 걸 러 내 고 지속 적 인 session 연결 을 제공 합 니 다.
3. Hibernate Interceptor 만약 에 어떤 hibernate 요청 이 웹 request 를 통 해 시 작 된 것 이 아니 라 quartz 와 같은 정시 작업 으로 시 작 된 것 이 있다 면 quartz 는 어떻게 해야만 hibernate session 을 얻 을 수 있 습 니까?해결책 은 Hibernate Interceptor 를 사용 하 는 것 이다.웹 요청 을 제어 (필터) 해서 이 루어 지 는 것 이 아니 라 는 것 이다.
4. 또 하 나 는 데이터베이스 에서 대상 을 게 으 름 으로 불 러 와 HQL 을 보 낼 때 특정한 설정 을 추가 해 야 한 다 는 것 이다.
struts 2 + spring + hibernate 게 으 름 로드 이상: org. hibernate. LazyInitialization 예외: lazily 초기 화 에 실 패 했 습 니 다
Hibernate 의 Lazy 가 1: n 관 계 를 초기 화 할 때 같은 Session 내부 에서 이 관계 집합 을 사용 해 야 합 니 다. 그렇지 않 으 면 Hiernate 는 이상 을 던 집 니 다: org. hibenate. Lazy Initialization Exception: failed to lazily initialize of...
이러한 이상 은 때때로 Hibernate 의 load 방법 으로 데이터 베 이 스 를 가 져 올 때 발생 하기 때문에 load 에서 나 오 는 대상 은 프 록 시 즉 프 록 시 대상 이 고 꺼 내 는 방법 이 실 행 된 후에 session 은 닫 힙 니 다. 이 프 록 시 대상 을 클 라 이언 트 가 jsp 페이지 를 분석 할 때 실제 SQL 문 구 를 보 낼 수 있 습 니 다. 이때 session 은 닫 혔 습 니 다.그래서 이 이상 을 던 질 것 이다.
해결 방법 은 다음 과 같다. (1) load 방법 대신 get 방법 을 사용 하지만 주의해 야 할 때 get 방법의 데이터 시트 가 다른 대상 과 연결 되 어 있 으 면 get 대상 에서 SQL 문 구 를 보 내지 않 고 이 이상 이 발생 할 수 있 습 니 다.(2) session 의 생명 주 기 를 확대 한다.Spring 에서 제공 하 는 filter: OpenSession InView 를 사용 할 수 있 습 니 다.전체 filter 설정 은 다음 과 같 습 니 다:
<filter>
   <filter-name>OpenSessionInView</filter-name>
   <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>OpenSessionInView</filter-name>
    <url-pattern>/*</url-pattern>       
</filter-mapping>

메모: 이 filter 는 웹. xml 파일 의 filter 이름 이 struts 2 앞 에 써 야 합 니 다.
프 록 시 를 초기 화 할 수 없 음 - 세 션 이상 없 음: org. hibernate. LazyInitializationException: proxy 를 초기 화 할 수 없 음 - org. hibernate. proxy. AbstractLazyInitializer. initialize (AbstractLazyInitializer. java: 57) at org. hibernate. proxy. AbstractLazyInitializer. getImplementation (AbstractLazyInitializer. java: 111)
원인: hibenate 3 many - to - one 의 기본 옵션 은 lazy = "proxy" 해결 방법: & 에 lazy = "false" 를 설정 합 니 다.
Hibernate 의 Lazy 가 1: n 관 계 를 초기 화 할 때 같은 Session 내부 에서 이 관계 집합 을 사용 해 야 합 니 다. 그렇지 않 으 면 Hiernate 는 이상 을 던 집 니 다: org. hibenate. Lazy Initialization Exception: failed to lazily initialize of...
두 가지 처리 방법
2. OpenSsionInViewFilter 필 터 를 사용 하여 hibenateFilter 필터 와 struts 2 필터 가 매 핑 될 때의 우선 순 위 를 주의 하 십시오.동시에 사물 처 리 를 설정 해 야 합 니 다. 그렇지 않 으 면 session 은 읽 기 전용 상태 에 있 고 수정, 삭제 할 수 없 는 동작 을 할 수 있 습 니 다.웹. xml 파일 에서 다음 과 같이 설정 합 니 다.
     <!-- Spring ApplicationContext         。 -->  
 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath*:spring/applicationContext.xml</param-value>
 </context-param>
 <!--           -->
 <filter>
  <filter-name>hibernateFilter</filter-name>
  <filter-class>
   org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
  </filter-class>
 </filter>

 <!--   Struts2 FilterDispatcher ,  GBK        struts2 action    。 -->
 <filter>
  <filter-name>struts2</filter-name>
  <filter-class>
   com.iman.nrms.opm.web.common.FilterDispatcher
  </filter-class>
  <init-param>
   <param-name>encoding</param-name>
   <param-value>GBK</param-value>
  </init-param>
 </filter>
 <filter>
         <filter-name>struts-cleanup</filter-name>
         <filter-class>
             org.apache.struts2.dispatcher.ActionContextCleanUp
         </filter-class>
     </filter>

 <filter-mapping>
  <filter-name>hibernateFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>

 <filter-mapping>
  <filter-name>struts2</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>

 <filter-mapping>
  <filter-name>struts-cleanup</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>

Hibernate 는 관련 대상, 속성 에 대한 로드 지연 을 허용 하지만 로드 지연 작업 이 같은 Hibernate Session 범위 내 에서 이 루어 질 수 있 도록 해 야 합 니 다.Service 층 이 로 딩 지연 기능 을 사용 한 영역 대상 을 웹 층 에 되 돌려 주면 로 딩 지연 이 필요 한 데이터 에 웹 층 이 접근 할 때 로 딩 영역 대상 의 Hibernate Session 이 종료 되 어 로 딩 지연 데이터 에 대한 접근 이 이상 합 니 다.Spring 이 제공 하 는 OpenSession InView Filter 필 터 는 이 문 제 를 잘 해결 해 주 었 습 니 다.OpenSessionInViewFilter 의 주요 기능 은 모든 요청 과정 을 Hibernate Session 에 연결 시 키 는 것 입 니 다. 최초의 업무 가 완료 되 었 더 라 도 웹 층 에서 로드 지연 작업 을 할 수 있 습 니 다.OpenSsionInViewFilter 필 터 는 Hibernate Session 을 요청 스 레 드 에 연결 합 니 다. Spring 의 사무 관리자 에 의 해 자동 으로 탐 지 됩 니 다.따라서 OpenSession InViewFilter 는 Service 층 에서 HibernateTransactionManager 나 JtaTransactionManager 를 사용 하여 사무 관 리 를 하 는 환경 에 적용 되 며, 사무 가 아 닌 읽 기 전용 데이터 작업 에 도 사용 할 수 있다.request – > open session – > 연결 을 열 고 사 무 를 시작 합 니 다 – > 지속 적 인 작업 – > 렌 더 링 (연결 닫 기, session) – > response 의 일부 과정 이 생략 되 어 관심 이 없습니다.
최근 에 하나의 프로젝트 를 만 들 고 있 는데 SSH 2 프레임 워 크 를 사용 하여 하나의 직렬 연결 기능 을 실현 하려 면 다음 과 같이 구체 적 으로 실현 해 야 한다.
Department 부 서 는 많은 하급 Department 를 포함 하고 있 습 니 다. 1 급 Department 를 조회 할 때 모든 것 이 OK 입 니 다. 그러나 1 급 Department 의 하위 Department 를 조회 할 때 다음 과 같은 오류 가 발생 했 습 니 다. 그 중에서 Department. hbm. xml 의 설정 파일 은?
CODE 에서 코드 영 화 를 보고 제 코드 영 화 를 파생 시 켰 습 니 다.
<many-to-one name="parent" class="Department"column="parentId"></many-to-one>  
        Department    parent    ,  parent   Department,        

Stacktraces
1、org.apache.jasper.JasperException:javax.el.ELException: Error reading ‘name’ on typecn.itcast.oa.domain.Department_$$_javassist_1
。。。。。생략
2、javax.el.ELException: Error reading ‘name’ ontype cn.itcast.oa.domain.Department_$$_
javassist_1
。。。。。생략
3、org.hibernate.LazyInitializationException:could not initialize proxy - no Session
。。。。。생략
위의 세 가지 오류 메시지 중 세 번 째 는 Lazy Initialization Exception (게 으 름 불 러 오기 이상 은 기본 적 인 상황 에서 hibenate 는 게 으 름 불 러 오기) 입 니 다. 이 는 데 이 터 를 읽 을 때 Session 이 종료 되 었 음 을 의미 합 니 다.
해결 방법:
1. 게 으 름 을 false 로 불 러 옵 니 다. 기본 적 인 상황 에서 hibenate 는 게 으 름 으로 불 러 옵 니 다. 따라서 게 으 름 으로 불 러 오지 않 고 Department. hbm. xml 에 다음 과 같이 설정 해 야 합 니 다.
<many-to-one name="parent"class="Department" column="parentId"lazy="false"></many-to-one>  
      lazy     false,    ,     Department ,     Department     ,           :  Department     Department ,       Department,       。

그러면 우 리 는 그 를 사용 할 때 만 불 러 오고 사용 하지 않 을 때 불 러 오지 않 을 수 있 습 니까?(기본 값 은 게 으 르 지만 사용 할 때 Session 을 찾 으 면 Session 을 찾 을 수 있 고 데이터베이스 에서 데 이 터 를 읽 을 수 있 습 니 다)
2. 차단기 사용
위 는 한 번 의 요청 을 대표 합 니 다. Action 과 차단 기 를 거 쳐 야 합 니 다. 왼쪽 사각형 은 Action 이 고 중간 사각형 은 Result (페이지) 이 며 오른쪽 사각형 은 Filter 차단기 입 니 다.
     Action          , Action     Service    (Service  ),         Service      ,  openSession close Session,      Result(  )           (  Session    )。        ,    close Session      Result     。        spring OpenSessionInViewFilter(       )   。

구체 적 인 코드 는 다음 과 같다.
Department. hbm. xml 의 설정 은 변 하지 않 습 니 다. 다음 과 같 습 니 다.
<many-to-one name="parent" class="Department"column="parentId"></many-to-one>  

웹. xml 에 필 터 를 추가 합 니 다. 다음 과 같 습 니 다.
<!--   Spring OpenSessionInViewFilter   ,   Hibernate      (LazyInitializationException) -->  
    <filter>  
       <filter-name>OpenSessionInViewFilter</filter-name>  
    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>  
    </filter>  
    <filter-mapping>  
       <filter-name>OpenSessionInViewFilter</filter-name>  
       <url-pattern>*.action</url-pattern>  
    </filter-mapping

이렇게 하면 필요 할 때 만 불 러 오고 필요 하지 않 을 때 불 러 오지 않 으 며 기본 페이지 는 게 으 름 으로 불 러 옵 니 다.
일반적으로 Filter 를 사용 하지 않 거나 lazy 를 false 로 설정 하지 않 으 면 Action 방법 에서 Session 을 사용 하고 나 면 Session 이 닫 히 기 때문에 Action 방법 외 에 Session 의 데 이 터 를 사용 하면 게 으 름 을 피 워 이상 을 불 러 옵 니 다.
     OpenSessionInViewFilter     Session     Filter ,  ,   Action     Session ,     Session        。

아래 의 이 그림 은 위의 이 그림 과 차이 가 많 지 않 으 니 참고 하 셔 도 됩 니 다.

좋은 웹페이지 즐겨찾기