hibenate 의 지연 로드 메커니즘

회전:http://blog.163.com/xi_zh_qi/blog/static/8501594200812695053939/
로드 지연:
   지연 로드 메커니즘 은 일부 불필요 한 성능 비용 을 피하 기 위해 제 기 된 것 이다. 지연 로드 란 데이터 가 진정 으로 필요 할 때 만 데이터 로드 작업 을 진정 으로 수행 하 는 것 이다.Hibernate 에 서 는 실체 대상 에 대한 지연 로 딩 과 집합 지연 로 딩 을 제공 합 니 다. 또한 Hibernate 3 에 서 는 속성 에 대한 지연 로 딩 도 제공 합 니 다.다음은 이러한 종류의 로드 지연 에 대한 세부 사항 을 소개 합 니 다.
A. 실체 대상 의 로드 지연:
실체 대상 에 게 로드 지연 을 사용 하려 면 실체의 맵 설정 파일 에 해당 하 는 설정 을 해 야 합 니 다. 다음 과 같 습 니 다.
<hibernate-mapping>

<class name=”com.neusoft.entity.User” table=”user” lazy=”true”>

    ……

</class>

</hibernate-mapping>

class 의 lazy 속성 을 true 로 설정 하여 실체의 지연 로드 기능 을 엽 니 다.다음 코드 를 실행 하면:
User user=(User)session.load(User.class,”1”);(1)
System.out.println(user.getName());(2)

(1) 곳 으로 실 행 될 때 Hibernate 는 데이터 에 대한 조 회 를 시작 하지 않 았 습 니 다. 만약 에 우리 가 이때 일부 디 버 깅 도구 (예 를 들 어 JBuilder 2005 의 Debug 도구) 를 통 해 이때 user 대상 의 메모리 스냅 샷 을 관찰 하면 우 리 는 놀 라 운 발견 을 할 수 있 습 니 다. 이때 돌아 올 수 있 는 것 은?
User $EnhancerByCGLIB $$bede 8986 유형의 대상 이 고 그 속성 은 null 입 니 다. 어떻게 된 일 입 니까?앞에서 제 가 말씀 드 렸 던 거 기억 나 요.
session. load () 방법 은 실체 대상 의 프 록 시 대상 을 되 돌려 줍 니 다. 여기 서 돌아 오 는 대상 유형 은 user 대상 의 프 록 시 대상 입 니 다.Hibernate 에 서 는 CGLIB 를 사용 하여 대상 의 프 록 시 대상 을 동적 으로 구성 하고 프 록 시 대상 에 대상 의 모든 속성 과 방법 을 포함 하 며 모든 속성 이 null 로 할당 된다.디 버 거 에 표 시 된 메모리 스냅 샷 을 통 해 알 수 있 듯 이 이 때 진정한 User 대상 은 프 록 시 대상 에 포함 되 어 있 습 니 다.
CGLIB$CALBACK_0. target 속성 에서 코드 가 (2) 로 실 행 될 때 user. getName () 방법 을 호출 합 니 다. 이 때 CGLIB 가 부여 한 리 셋 메커니즘 을 통 해 실제 호출 됩 니 다.
CGLIB$CALBACK_0. getName () 방법, 이 방법 을 호출 할 때 Hibernate 는 CGLIB $CALBACK 를 먼저 검사 합 니 다.0. target 속성 이 null 인지, 비어 있 지 않 으 면 대상 의 getName 방법 을 호출 합 니 다. 비어 있 으 면 데이터베이스 조 회 를 시작 하여 이러한 SQL 문 구 를 생 성 합 니 다.
select * from user where id=’1’;데 이 터 를 조회 하고 대상 을 구성 하 며 값 을 부여 합 니 다.
CGLIB$CALBACK_0. target 속성 중.
    이렇게 해서 중간 에이전트 대상 을 통 해 Hibernate 는 실체의 지연 로드 를 실 현 했 습 니 다. 사용자 가 실제 대상 속성 을 얻 는 동작 을 시작 할 때 만 데이터베이스 조회 작업 을 할 수 있 습 니 다.따라서 실체의 지연 로드 는 중간 프 록 시 클래스 를 통 해 이 루어 지기 때문에 session. load () 방법 만 실체 지연 로드 를 이용 할 수 있 습 니 다. session. load () 방법 만 실체 클래스 의 프 록 시 대상 으로 돌아 갈 수 있 기 때 문 입 니 다.
B、        집합 형식의 지연 로드:
Hibernate 의 지연 로 딩 메커니즘 에서 집합 유형 에 대한 응용 은 가장 중요 한 의 미 를 가진다. 이 는 성능 을 대폭 향상 시 킬 수 있 기 때문에 Hibernate 는 JDK Collection 에 대한 독립 적 인 실현 을 포함 하여 많은 노력 을 기 울 였 다. 우 리 는 한 쌍 의 다 중 관련 에서 관련 대상 을 수용 하 는 Set 집합 을 정의 했다.java. util. set 형식 이나 하위 형식 이 아니 라 net. sf. hibenate. collection. set 형식 입 니 다. 사용자 정의 집합 클래스 를 사용 하여 Hibernate 는 집합 형식의 지연 로 딩 을 실현 합 니 다.집합 형식 에 대한 로드 지연 을 사용 하기 위해 서 는 다음 과 같이 우리 의 실체 류 와 관련 된 부분 을 설정 해 야 합 니 다.
<hibernate-mapping>

    <class name=”com.neusoft.entity.User” table=”user”>

…..

<set name=”addresses” table=”address” lazy=”true” inverse=”true”>

<key column=”user_id”/>

<one-to-many class=”com.neusoft.entity.Arrderss”/>

</set>

    </class>

</hibernate-mapping>

   <set>   lazy     true              。        :

User user=(User)session.load(User.class,”1”);

Collection addset=user.getAddresses();       (1)

Iterator it=addset.iterator();                (2)

while(it.hasNext()){

Address address=(Address)it.next();

System.out.println(address.getAddress());

}

프로그램 이 (1) 곳 으로 실 행 될 때 관련 데이터 에 대한 조 회 를 시작 하지 않 고 (2) 곳 으로 실 행 될 때 만 실제 데이터 읽 기 작업 이 시 작 됩 니 다. 이때 Hibernate 는 캐 시 에 있 는 조건 에 맞 는 데이터 인덱스 에 따라 조건 에 맞 는 실체 대상 을 찾 습 니 다.
여기 서 우 리 는 새로운 개념 인 데이터 색인 을 도입 했다. 다음은 데이터 색인 이 무엇 인지 먼저 연결 할 것 이다.Hibernate 에서 집합 형식 을 캐 시 할 때 두 부분 으로 나 누 어 캐 시 합 니 다. 먼저 캐 시 집합 에 있 는 모든 실체의 id 목록 을 모 은 다음 에 실체 대상 을 캐 시 합 니 다. 이런 실체 대상 의 id 목록 은 바로 데이터 색인 입 니 다.데이터 색인 을 찾 을 때 해당 하 는 데이터 색인 을 찾 지 못 하면 select SQL 이 실행 되 고 조건 에 맞 는 데 이 터 를 얻 으 며 실체 대상 집합 과 데이터 색인 을 구성 한 다음 실체 대상 의 집합 으로 돌아 가 실체 대상 과 데이터 색인 을 Hibernate 캐 시 에 포함 시 킵 니 다.다른 한편, 해당 하 는 데이터 인덱스 를 찾 으 면 데이터 인덱스 에서 id 목록 을 꺼 내 고 id 에 따라 캐 시 에서 해당 하 는 실 체 를 찾 습 니 다. 찾 으 면 캐 시 에서 되 돌려 주 고 찾 지 못 하면 select SQL 조 회 를 시작 합 니 다.여기 서 우 리 는 또 다른 문 제 를 알 아 냈 다. 이 문 제 는 성능 에 영향 을 미 칠 수 있다. 이것 이 바로 집합 유형의 캐 시 정책 이다.만약 우리 가 다음 과 같이 집합 유형 을 설정 한다 면:
<
hibernate-mapping>

    <class name=”com.neusoft.entity.User” table=”user”>

…..

<set name=”addresses” table=”address” lazy=”true” inverse=”true”>

<cache usage=”read-only”/>

<key column=”user_id”/>

<one-to-many class=”com.neusoft.entity.Arrderss”/>

</set>

    </class>

</hibernate-mapping>

여기 서 저 희 는 < cache usage = "read - only" / > 설정 을 사 용 했 습 니 다. 이 정책 으로 집합 형식 을 설정 하면 Hibernate 는 데이터 색인 만 캐 시 하고 집합 중인 실체 대상 은 캐 시 하지 않 습 니 다.다음 코드 를 실행 할 수 있 도록 위 설정:
User user=(User)session.load(User.class,”1”);

Collection addset=user.getAddresses();      

Iterator it=addset.iterator();               

while(it.hasNext()){

Address address=(Address)it.next();

System.out.println(address.getAddress());

}

System.out.println(“Second query……”);

User user2=(User)session.load(User.class,”1”);

Collection it2=user2.getAddresses();

while(it2.hasNext()){

Address address2=(Address)it2.next();

System.out.println(address2.getAddress());

}

이 코드 를 실행 하면 다음 과 같은 출력 을 얻 을 수 있 습 니 다:
Select * from user where id=’1’;

Select * from address where user_id=’1’;

Tianjin

Dalian

Second query……

Select * from address where id=’1’;

Select * from address where id=’2’;

Tianjin

Dalian

우 리 는 두 번 째 조 회 를 실 행 했 을 때 address 표 에 대한 두 가지 조회 작업 을 실 행 했 는데 왜 이러 는 지 보 았 다.이 는 첫 번 째 로 실 체 를 불 러 온 후 집합 형식 캐 시 정책 설정 에 따라 집합 데이터 인덱스 만 캐 시 했 을 뿐 집합 중인 실체 대상 은 캐 시 하지 않 았 기 때문에 두 번 째 로 실 체 를 다시 불 러 올 때 Hibernate 는 해당 실체의 데이터 인덱스 를 찾 았 으 나 데이터 인덱스 에 따라 캐 시 에서 해당 하 는 실 체 를 찾 을 수 없 었 다.그래서 Hibernate 는 찾 은 데이터 인덱스 에 따라 두 개의 select SQL 조회 작업 을 시 작 했 는데 이것 은 성능 에 대한 낭 비 를 초래 했 습 니 다. 어떻게 해야만 이런 상황 을 피 할 수 있 습 니까?우 리 는 집합 형식의 실체 에 대해 서도 캐 시 정책 을 지정 해 야 하기 때문에 다음 과 같이 집합 유형 을 설정 해 야 합 니 다.
<hibernate-mapping>

    <class name=”com.neusoft.entity.User” table=”user”>

…..

<set name=”addresses” table=”address” lazy=”true” inverse=”true”>

<cache usage=”read-write”/>

<key column=”user_id”/>

<one-to-many class=”com.neusoft.entity.Arrderss”/>

</set>

    </class>

</hibernate-mapping>

이 때 Hibernate 는 집합 형식의 실체 도 캐 시 합 니 다. 이 설정 에 따라 위의 코드 를 다시 실행 하면 다음 과 같은 출력 을 얻 을 수 있 습 니 다.
Select * from user where id=’1’;

Select * from address where user_id=’1’;

Tianjin

Dalian

Second query……

Tianjin

Dalian

이 때 데이터 색인 에 따라 조회 하 는 SQL 문 구 는 더 이상 없 을 것 입 니 다. 캐 시 에서 집합 형식 에 저 장 된 실체 대상 을 직접 얻 을 수 있 기 때 문 입 니 다.
C、       속성 지연 로드:
   Hibernate 3 에 서 는 새로운 특성 인 속성의 지연 로드 를 도입 하 였 으 며, 이 메커니즘 은 고성능 조 회 를 얻 기 위해 강력 한 도 구 를 제공 하 였 다.앞에서 우리 가 빅 데이터 대상 을 읽 을 때 User 대상 에 resume 필드 가 있 습 니 다. 이 필드 는 자바 sql. Clob 형식 으로 사용자 의 이력서 정 보 를 포함 하고 있 습 니 다. 우리 가 이 대상 을 불 러 올 때 이 필드 를 불 러 올 수 밖 에 없습니다. 우리 가 정말 필요 하 든 안 하 든.그리고 이런 빅 데이터 대상 의 읽 기 자체 가 큰 성능 비용 을 가 져 올 수 있다.Hibernate 2 에서 우 리 는 앞에서 말 한 면 성능 의 입도 세분 화 를 통 해 User 류 를 분해 하여 이 문 제 를 해결 할 수 있 습 니 다 (그 절의 논술 을 참조 하 십시오). 그러나 Hibernate 3 에서 우 리 는 속성 지연 로드 체 제 를 통 해 이 필드 를 진정 으로 조작 해 야 할 때 만 이 필드 데 이 터 를 읽 는 능력 을 얻 을 수 있 습 니 다.이 를 위해 우 리 는 다음 과 같이 우리 의 실체 클래스 를 설정 해 야 합 니 다.
<hibernate-mapping>

<class name=”com.neusoft.entity.User” table=”user”>

……

<property name=”resume” type=”java.sql.Clob” column=”resume” lazy=”true”/>

    </class>

</hibernate-mapping>
< property > 요소 의 lazy 속성 설정 true 를 통 해 속성의 지연 로 딩 을 엽 니 다. Hibernate 3 에서 속성의 지연 로 딩 을 실현 하기 위해 클래스 인 텐 시파 이 어 를 사용 하여 실체 클래스 의 Class 파일 을 강화 처 리 했 습 니 다. 인 텐 시파 이 어 를 통 해 CGLIB 의 리 턴 메커니즘 논 리 를 실체 클래스 에 추가 하면 속성의 지연 로 딩 을 알 수 있 습 니 다.CGLIB 를 통 해서 이 루어 진 거 야?CGLIB 는 Apache 의 오픈 소스 프로젝트 입 니 다. 이 라 이브 러 리 는 자바 류 의 바이트 코드 를 조작 할 수 있 고 바이트 코드 에 따라 요구 에 부 합 된 클래스 대상 을 동적 으로 구성 할 수 있 습 니 다.위의 설정 에 따라 아래 코드 를 실행 합 니 다:
String sql=”from User user where user.name=’zx’ ”;

Query query=session.createQuery(sql);    (1)

List list=query.list();

for(int i=0;i<list.size();i++){

User user=(User)list.get(i);

System.out.println(user.getName());

System.out.println(user.getResume());    (2)

}

(1) 에 실 행 될 때 다음 과 같은 SQL 문 구 를 생 성 합 니 다.
Select id,age,name from user where name=’zx’;
이 때 Hibernate 는 User 실체 에서 불 러 오 는 속성 에 대응 하 는 필드 데 이 터 를 모두 검색 합 니 다. (2) 에 실 행 될 때 다음 과 같은 SQL 문 구 를 생 성 합 니 다.
Select resume from user where id=’1’;
이 때 resume 필드 데이터 에 대한 진정한 읽 기 동작 이 시 작 됩 니 다.

좋은 웹페이지 즐겨찾기