[하이버네이트] 2차 캐싱 적용하기
참조
Java Persistence With Hibernate
http://whiteship.tistory.com/1256
Improving Hibernate's Performance
19.2. The Second Level Cache
Hibernate: Truly Understanding the Second-Level and Query Caches
Hibernate Caching
이론적으로 정리할 것 들
- 2차 캐싱이라고 하는 이유? 1차 캐시(persistence context cache)는 있으니깐.
- 하이버네이트 캐싱 종류(트랜잭션 스콥 캐싱, 프로세스 스콥 캐싱, 클러스터 스콥 캐싱)
- 캐싱에 적당한 클래스(데이터 변경이 드물고, (금전적인 데이터 처럼)핵심적인 데이터가 아니며, 공유하는 데이터가 아니고 애플리케이션에 국한된 데이터)
- 동시성 전략(Transactional, Read-write, Nonstrict-read-write, Read-only)
- 캐싱 공급자 선택하기(EHCache, OSCache, SwarmCacahe, JBoss Cache)
적용하기
1. 캐싱 동시성 전략 선택하기
read-wirte 모드를 선택함. read committed isolation 수준을 유지하려고.
@Entity
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class Study implements Serializable{
2. SessionFactory 설정에 2차 캐싱 관련 설정 추가.
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="springsprout.domain" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.generate_statistics">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.EhCacheProvider</prop>
</props>
</property>
</bean>
2차 캐시와 함께 쿼리 캐시도 켜주고, 사용할 캐싱 공급자를 설정해 줍니다.
3. Query 또는 Criteria API에 cacheable 설정 true로 변경.
기본값이 false기 때문에 이렇게 해주지 않으면 캐시가 적용되지 않습니다.
public List<Study> getStudyList() {
Criteria c = getCurrentSession().createCriteria(Study.class);
c.setCacheable(true);
return c.list();
}
4. 테스트
@Test
public void getAll() throws Exception {
insertXmlData("testData.xml");
assertThat(sr.getStudyList().size(), is(2));
assertThat(sr.getStudyList().size(), is(2));
}
콘솔에 select 쿼리가 한 번만 찍히는지 확인합니다.
5. (optional) ehcache.xml 설정 파일 추가.
<ehcache>
<diskStore path="java.io.tmpdir"/>
<defaultCache maxElementsInMemory="500" eternal="true"
overflowToDisk="false" memoryStoreEvictionPolicy="LFU" />
<cache name="springsprout.domain.study.Study"
maxElementsInMemory="500" eternal="true" overflowToDisk="false"
memoryStoreEvictionPolicy="LFU" />
<cache name="springsprout.domain.study.Meeting"
maxElementsInMemory="500" eternal="true" overflowToDisk="false"
memoryStoreEvictionPolicy="LFU" />
<cache name="org.hibernate.cache.StandardQueryCache"
maxElementsInMemory="5" eternal="false" timeToLiveSeconds="120"
overflowToDisk="true" />
<cache name="org.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="5000" eternal="true" overflowToDisk="true" />
</ehcache>
이런식으로 만든다음 src 폴더 바로 밑에 추가해주면 끝.
6. 고민하기
- 콘솔을 눈으로 확인하는;; 수동 테스트인데 이걸 어떻게 하면 자동화 테스트로 바꿀 수 있을까요. 흠..
- SessionFactory 자체에 아예 모든 Qeury와 Criteria가 캐시를 사용하도록 설정할 수는 없을까요?
- 스프링 AOP를 이용한 애플리케이션 차원의 캐시와 지금 사용한 시스템적인 캐시 중에 어떤것을 어떤 경우에 사용해야 적당한 것일까?