Hibernate 캐시 상세 정보

19677 단어 Hibernate캐시
1. 캐시란 무엇입니까?
데이터베이스 캐시는 응용 프로그램과 물리적 데이터 원본 사이의 데이터를 가리킨다.물리적 데이터 원본의 데이터를 캐시로 복사하는 것이다.캐시가 있으면 응용 프로그램이 물리적 데이터 원본에 대한 접근 빈도를 낮추어 효율을 높일 수 있다.캐시된 미디어는 일반적으로 메모리일 수도 있고 하드디스크일 수도 있다.
Hibernate의 캐시는 세 가지 유형이 있는데 그것이 바로 1급 캐시, 2급 캐시, 조회 캐시입니다.
2.1 레벨 캐시
1레벨 캐시는 Session 캐시로 Session에서 자동으로 관리되며 프로그램이 관여할 필요가 없습니다.1 레벨 캐시는 객체의 ID에 따라 로드되고 캐시됩니다.다음 코드:

@Override
  public void testCache() {
    // TODO Auto-generated method stub
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction(); 
    Course c = (Course) session.get(Course.class, 1);
    System.out.println("Name:" + c.getName());
    c = (Course) session.get(Course.class, 1);
    System.out.println("Name:" + c.getName());
    tx.commit();
    session.close();
  }
실행 결과:

Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
Name: 
Name: 
첫 번째 조회 때 SQL 문장을 생성하고 조회된 대상을 1급 캐시에 넣고, 두 번째 조회 때 1급 캐시에서 직접 이 대상을 찾으면 SQL 문장을 다시 생성할 필요가 없다.
다시 한 번 예를 들자.

@Override
  public void testCache() {
    // TODO Auto-generated method stub
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction(); 
    Course c = (Course) session.get(Course.class, 1);
    System.out.println("Name:" + c.getName());
    tx.commit();
    session.close();
    session = sessionFactory.openSession();
    tx = session.beginTransaction(); 
    c = (Course) session.get(Course.class, 1);
    System.out.println("Name:" + c.getName());
    tx.commit();
    session.close();
  }
1 레벨 캐시는 Session 레벨의 캐시이기 때문에 Session이 닫힌 후에 1 레벨 캐시도 존재하지 않습니다. 두 번째 조회도 SQL 문장을 생성해야 합니다.

Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
Name: 
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
Name: 
 3. 2 레벨 캐시
2 레벨 캐시는 SessionFactory 캐시입니다. 1 레벨 캐시와 유사하고 대상의 ID에 따라 캐시를 불러오고 캐시합니다. 차이점은 1 레벨 캐시는 Session 내에서만 유효하고 2 레벨 캐시는 SessionFactory 내에서만 유효하다는 것입니다.ID의 객체에 액세스할 때 먼저 1레벨 캐시에서 찾고 찾을 수 없으면 2레벨 캐시에서 찾습니다.2단계 캐시는 EHCache, OSCache, SwarmCache와 JBossCache 등을 포함한다.여기에는 EHCache를 예로 들 수 있습니다.
2단계 캐시는 프로그램이 관리해야 한다.먼저 Maven 다운로드와 관련된 Jar를 구성하여 pom 파일에 추가합니다.

<dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-ehcache</artifactId> 
      <version>4.1.0.Final</version> 
    </dependency>
    <dependency> 
      <groupId>net.sf.ehcache</groupId> 
      <artifactId>ehcache</artifactId> 
      <version>2.8.3</version> 
    </dependency>
EHCache 프로필 ehcache를 만듭니다.xml:

<ehcache>
  <diskStore path="E:\Eclipse\MyWorkspace\Cache"/>
  <defaultCache
    maxElementsInMemory="10000"
    eternal="true"
    timeToIdleSeconds="120"
    timeToLiveSeconds="120"
    overflowToDisk="true"
  />
  <cache name="com.hzhi.course.entity.Course"
    maxElementsInMemory="10000"
    eternal="true"
    timeToIdleSeconds="300"
    timeToLiveSeconds="600"
    overflowToDisk="true"
  />
</ehcache>
defaultCache는 기본 설정입니다. 다음 cache는 어떤 클래스에 대해 2단계 캐시를 하는지 가리킵니다.안에 최대 캐시의 대상 수량을 설정했습니다. 영구적으로 유효한지, 최대 유휴 초수, 최대 생존 초수, 메모리가 가득 찼을 때 하드디스크에 쓰였는지, 하드디스크에 쓰인 경로 등입니다.
캐시가 필요한 클래스의 hbm 파일 수정:

 <class name="com.hzhi.course.entity.Course" table="clas">
    <cache usage="read-only"/>
        ......
  </class>
usage는 병렬 접근 정책을 설정합니다. 일반적으로read-only로 설정합니다.
응용 프로그램 컨텍스트를 수정합니다.xml의 SessionFactory 설정으로 2단계 캐시의 속성을 추가합니다.

<!-- SessionFactory -->
   <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" >
      <ref local="dataSource"/>
    </property>
    <!--  Hibernate  -->
    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
        <prop key="hibernate.show_sql">true</prop>
        <prop key="hibernate.format_sql">true</prop>
        <prop key="hibernate.connection.isolation">8</prop>
        <!--   -->
        <prop key="hibernate.cache.use_second_level_cache">false</prop>
        <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>        
        <prop key="hibernate.cache.provider_configuration_file_resource_path">WEB-INF/ehcache.xml</prop>        
      </props>
    </property>
     ......
   </bean>
다음 예제를 실행합니다.

@Override
  public void testCache() {
    // TODO Auto-generated method stub
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction(); 
    Course c = (Course) session.get(Course.class, 1);
    System.out.println("Name:" + c.getName());
    tx.commit();
    session.close();
    session = sessionFactory.openSession();
    tx = session.beginTransaction(); 
    c = (Course) session.get(Course.class, 1);
    System.out.println("Name:" + c.getName());
    tx.commit();
    session.close();
  }
결과:

Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
Name: 
Name: 
세션을 닫았지만 2단계 캐시가 존재하기 때문에 SQL 문장을 한 번만 생성했습니다.
다음 예:

@Override
  public void testCache() {
    // TODO Auto-generated method stub
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction(); 
    Query query = session.createQuery("from Course"); 
    Iterator iter = query.iterate(); 
    while(iter.hasNext()){ 
        System.out.println(((Course)iter.next()).getName()); 
    }
    tx.commit();
    session.close();
    
    session = sessionFactory.openSession();
    tx = session.beginTransaction(); 
    query = session.createQuery("from Course"); 
    iter = query.iterate(); 
    while(iter.hasNext()){ 
        System.out.println(((Course)iter.next()).getName()); 
    }
    tx.commit();
    session.close();
  }
결과:

Hibernate: 
  select
    course0_.ID as col_0_0_ 
  from
    clas course0_
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
 
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
 
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
 
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
C 
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
 A
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
Java
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
Linux
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
 
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
 
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
 
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
 
Hibernate: 
  select
    course0_.ID as col_0_0_ 
  from
    clas course0_
 
 
 
C 
 A
Java
Linux
 
 
 
 
Query의list() 방법을 사용할 때, SQL 문장을 한 번만 생성하여 모든 대상을 조회하고, iterate () 방법을 사용할 때, 모든 대상의 ID를 먼저 얻은 다음, 각 ID에 따라 SQL 문장 조회를 생성합니다.두 번째 세션에서는 iterate () 방법을 사용합니다. 먼저 SQL 문장을 한 번 생성하고 ID를 얻은 다음에 ID에 따라 대상을 찾습니다. 2단계 캐시를 켜서 2단계 캐시에서 대상을 찾았기 때문에 직접 출력했습니다. 각 ID에 따라 SQL 문장을 만들지 않았습니다.
1레벨 캐시든 2레벨 캐시든 모두 대상만 캐시할 수 있고 속성의 값을 캐시할 수 없습니다.다음 예:

@Override
  public void testCache() {
    // TODO Auto-generated method stub
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction(); 
    Query query = session.createQuery("select c.name from Course c");  
    List<String> names = query.list(); 
    for(Iterator iter = names.iterator(); iter.hasNext();){ 
      String name = (String) iter.next(); 
      System.out.println(name); 
    } 
    System.out.println("----------"); 
    query = session.createQuery("select c.name from Course c");  
    names = query.list(); 
    for(Iterator iter = names.iterator(); iter.hasNext();){ 
      String name = (String) iter.next(); 
      System.out.println(name); 
    } 
    System.out.println("----------"); 
    tx.commit();
    session.close();
  }
실행 결과:

Hibernate: 
  select
    course0_.NAME as col_0_0_ 
  from
    clas course0_
 
 
 
C 
 A
Java
Linux
 
 
 
 
----------
Hibernate: 
  select
    course0_.NAME as col_0_0_ 
  from
    clas course0_
 
 
 
C 
 A
Java
Linux
 
 
 
 
----------
2단계 캐시를 열었지만 검색 결과는 대상이 아니라 속성이기 때문에 캐시가 없습니다. 두 번째 검색은 검색 문장을 생성했습니다.이 문제를 해결하려면 검색 캐시가 필요합니다.
3. 쿼리 캐시
2단계 캐시를 설정한 토대에서 검색 캐시를 설정할 수 있고 SessionFactory 설정에 한 줄을 추가할 수 있습니다.<prop key="hibernate.cache.use_query_cache">true</prop>쿼리 캐시가 열립니다.쿼리 캐시도 SessionFactory 레벨의 캐시로 전체 SessionFactory에서 유효합니다.
2단계 캐시를 닫고 다음 예를 실행하여Query 뒤에 setCacheable(true)를 추가하여 쿼리 캐시를 엽니다.

@Override
  public void testCache() {
    // TODO Auto-generated method stub
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction(); 
    Query query = session.createQuery("select c.name from Course c"); 
    query.setCacheable(true); 
    List<String> names = query.list(); 
    for(Iterator iter = names.iterator(); iter.hasNext();){ 
      String name = (String) iter.next(); 
      System.out.println(name); 
    } 
    System.out.println("----------"); 
    query = session.createQuery("select c.name from Course c"); 
    query.setCacheable(true); 
    names = query.list(); 
    for(Iterator iter = names.iterator(); iter.hasNext();){ 
      String name = (String) iter.next(); 
      System.out.println(name); 
    } 
    System.out.println("----------"); 
    tx.commit();
    session.close();
  }
결과:

Hibernate: 
  select
    course0_.NAME as col_0_0_ 
  from
    clas course0_
 
 
 
C 
 A
Java
Linux
 
 
 
 
----------
 
 
 
C 
 A
Java
Linux
 
 
 
 
----------
두 번 조회한 HQL 문장은 일치하기 때문에 SQL 문장은 한 번만 생성됩니다.하지만 두 번째 검색을 바꾸면:

System.out.println("----------"); 
    query = session.createQuery("select c.name from Course c where c.id > 5"); 
    query.setCacheable(true); 
    names = query.list(); 
    for(Iterator iter = names.iterator(); iter.hasNext();){ 
      String name = (String) iter.next(); 
      System.out.println(name); 
    } 
    System.out.println("----------");
결과:

Hibernate: 
  select
    course0_.NAME as col_0_0_ 
  from
    clas course0_
 
 
 
C 
 A
Java
Linux
 
 
 
 
----------
Hibernate: 
  select
    course0_.NAME as col_0_0_ 
  from
    clas course0_ 
  where
    course0_.ID>5
 A
Java
Linux
 
 
 
 
----------
HQL 문장이 바뀌었기 때문에 두 번째 SQL 문장도 생성되었습니다.
쿼리 캐시는 속성을 캐시할 수도 있고 객체를 캐시할 수도 있지만 객체를 캐시할 때 객체의 ID만 캐시되고 전체 객체는 캐시되지 않습니다.다음 예:

@Override
  public void testCache() {
    // TODO Auto-generated method stub
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction(); 
    Query query = session.createQuery("from Course");
    query.setCacheable(true);
    List<Course> list = query.list();
    for (int i=0; i<list.size(); i++){
      System.out.println(list.get(i).getName()); 
    }
    System.out.println("----------"); 
    tx.commit();
    session.close();
    session = sessionFactory.openSession();
    tx = session.beginTransaction();    
    query = session.createQuery("from Course"); 
    query.setCacheable(true);
    list = query.list();
    for (int i=0; i<list.size(); i++){
      System.out.println(list.get(i).getName()); 
    }
    System.out.println("----------");
    tx.commit();
    session.close();
  }
결과:

 Hibernate: 
  select
    course0_.ID as ID0_,
    course0_.NAME as NAME0_,
    course0_.COMMENT as COMMENT0_ 
  from
    clas course0_
 
 
 
C 
 A
Java
Linux
 
 
 
 
----------
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
Hibernate: 
  select
    course0_.ID as ID0_0_,
    course0_.NAME as NAME0_0_,
    course0_.COMMENT as COMMENT0_0_ 
  from
    clas course0_ 
  where
    course0_.ID=?
 
 
 
C 
 A
Java
Linux
 
 
 
 
----------
쿼리 캐시를 열었기 때문에 2단계 캐시를 열지 않았습니다.list () 방법을 사용하여 한 번에 모든 대상을 조회했지만 쿼리 캐시는 대상 ID만 캐시하고 전체 대상을 캐시하지 않았습니다.그래서 두 번째 세션에서'from Course'라는 HQL은 앞의 것과 같아서 SQL 문장을 생성하지 않았지만 2단계 캐시를 열지 않았고 전체 대상을 캐시하지 않았기 때문에 각 ID에 따라 SQL 문장을 한 번만 생성할 수 있습니다.두 번 모두list() 방법을 사용했지만 첫 번째는 SQL 문장을 생성하여 한 번에 모든 대상을 조회하고, 두 번째는 조회 캐시에 있는 ID에 따라 하나씩 SQL 문장을 생성합니다.
쿼리 캐시와 L2 캐시를 동시에 열면 두 번째 세션에서는 ID에 따라 SQL 문구를 생성할 필요가 없습니다.

Hibernate: 
  select
    course0_.ID as ID0_,
    course0_.NAME as NAME0_,
    course0_.COMMENT as COMMENT0_ 
  from
    clas course0_
 
 
 
C 
 A
Java
Linux
 
 
 
 
----------
 
 
 
C 
 A
Java
Linux
 
 
 
 
----------
이상은 본문의 전체 내용입니다. 본고의 내용이 여러분의 학습이나 업무에 일정한 도움을 줄 수 있는 동시에 저희를 많이 지지해 주시기 바랍니다!

좋은 웹페이지 즐겨찾기