1차 캐시 영속성 컨텍스트 내부에는 엔티티를 보관하는 저장소트랜잭션이 시작하고 종료할 때 까지만 1차 캐시가 유효하다. (일반적인 경우) 클라이언트의 요청이 들어올 때부터 끝날때 까지만 1차 캐시가 유효하다. (OSIV를 사용하는 경우) 데이터베이스 접근 횟수를 획기적인 정도로 줄여주는 건 아니다. Entity Manager로 조회하거나 변경하는 모든 엔티티는 1차 캐시에 저장된다. 1차 캐시는 임의로 on/off할 수 있는 옵션이 아니다. 영속성 컨텍스트 자체가 사실상 1차 캐시와 같다고 볼 수 있다. 동작 순서find 호출 영속성 컨텍스트에 캐시된 데이터 조회 if(Data X) DB 접근 및 데이터 로드 후 1차 캐시 데이터에 저장 결과 반환 단, 최초 조회시에는 바로 DB에서 조회한다. 같은 엔티티를 조회하는 경우에 1차 캐시에에서 조회한다. 2차 캐시 (= 공유 캐시) 하이버네이트를 포함한 대부분의 JPA 구현체들이 지원하는 애플리케이션 범위의 캐시 애플리케이션을 종료할 때까지 유지되는 캐시 분산 캐시나 클러스터링 환경의 캐시는 애플리케이션보다 더 오래 유지 될 수도 있다. 동작 순서find 호출 2차 캐시에서 우선조회 if(Data X) DB 접근 및 데이터 로드 후 2차 캐시 데이터에 저장 해당 엔티티를 복사 복사한 엔티티를 반환 2차 캐시를 적절히 활용하면 데이터베이스 조회 횟수를 획기적으로 줄일 수 있다. 1차 캐시와 다르게 조회환 엔티티가 아닌 조회한 엔티티의 복사복을 반환한다. 2차 캐시는 영속성 유닛 범위의 캐시다. 2차 캐시도 데이터베이스 기본 키를 기준으로 캐싱한다.단, 영속성 컨텍스트가 다르면 동일성을 보장하지 않는다. 2차 캐시 사용법 - 공통 @Cacheable : 엔티티 캐시 적용시 사용하는 어노테이션 캐시 모드 설정 (properties 파일에서 설정)예시 : spring.jpa.properties.javax.persistence.sharedCache.mode=ENABLE_SELECTIVE 속성 종류 (1) ALL : 모든 엔티티를 캐시한다. (2) NONE : 캐시를 사용하지 않는다. (3) ENABLE_SELECTIVE : Cacheable(true)로 설정된 엔티티만 캐시를 적용한다. (주사용) (4) DISABLE_SELECTIVE : 모든 엔티티를 캐시하는데 Cacheable(false)만 캐시하지 않는다 (5) UNSPECIFIED : JPA 구현체가 정의한 설정을 따른다 캐시 모드 설정 방법 (properties 파일에 속성 값 추가하기) #캐시 모드 설정
spring.jpa.properties.javax.persistence.sharedCache.mode = ENABLE_SELECTIVE
캐시 조회 모드 설정USE : 캐시에서 조회한다. (기본값) BYPASS : 캐시를 무시하고 데이터베이스에 직접 접근한다. 캐시 저장 방식 설정USE : 조회한 데이터를 캐시에 저장. (기본값) (1) 조회한 데이터가 이미 캐시에 있으면 캐시 데이터를 최신 상태로 갱신하지는 않는다. (2) 트랜잭션을 커밋하면 등록/수정한 엔티티도 캐시에 저장한다. BYPASS : 캐시에 저장하지 않는다. REFRESH : USE 전략에 추가로 데이터베이스에서 조회한 엔티티를 최신 상태로 다시 캐시한다. 캐시 조회/저장 방식 설정에 대한 예시 //Entity Manager 범위 적용
em . setProperty ( "javax.persistence.cache.retrieveMode" , CacheRetrieveMode . BYPASS );
//find()
Map & lt ; String , Object & gt ; param = new HashMap & lt ; String , Object & gt ;();
param . put ( "javax.persistence.cache.retrieveMode" , CacheRetrieveMode . BYPASS );
param . put ( "javax.persistence.cache.storeMode" , CacheStoreMode . BYPASS );
em . find ( SomeEntity . class , id , param );
2차 캐시 사용법 - JPA javax.persistence.Cache 인터페이스 제공 public interface Cache {
// 해당 엔티티가 캐시에 있는지 여부 확인
public boolean contains ( Class cls , Object primaryKey );
// 해당 엔티티중 특정 식별자를 가진 엔티티를 캐시에서 제거
public void evict ( Class cls , Object primaryKey );
// 해당 엔티티 전체를 캐시에서 제거
public void evict ( Class cls );
// 모든 캐시 데이터 제거
public void evictAll ();
// JPA Cache 구현체 조회
public < T > T unwrap ( Class < T > cls );
}
public interface Cache {
//캐시 관리 객체 조회
Cache cache = emf . getCache ();
boolean contains = cache . contains ( SomeEntity . class , someEntity . getId ());
}
2차 캐시 사용법 - 하이버네이트 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
- @Cache : 하이버네이트에서 제공하는 캐시 설정 어노테이션
- 캐시와 관련된 더 세밀한 설정을 할 때 사용
- 컬렉션 캐시를 적용할 때에도 사용
- @Cache 어노테이션의 속성
- usage : CacheConcurrencyStrategy 를 사용해서 캐시 동시성 전략을 설정
(1) NONE : 캐시 설정 X
(2) READ_ONLY :
- 읽기 전용 설정
- 등록/삭제 가능
- 수정 불가능
- 읽기 전용인 불변 객체는 수정 X → 2차 캐시 조회 시 객체를 복사하지 않고 원본 객체를 반환
(3) NONSTRICT_READ_WRITE :
- 엄격하지 않은 읽고 쓰기 전략
- 동시에 같은 엔티티 수정 시 데이터 일관성이 깨질 수 있다.
- EHCACHE는 데이터 수정 시 캐시 데이터를 무효화
(4) READ_WRITE :
- 읽기/쓰기 가능
- READ COMMITTED 정도의 격리 수준을 보장
- EHCACHE는 데이터 수정 시 캐시 데이터도 같이 수정
(5) TRANSACTIONAL :
- 컨테이너 관리 환경에서 사용 가능
- 설정에 따라 REPEATABLE READ 정도의 격리 수준을 보장
- region : 캐시 지역 설정
- include : 연관 객체를 캐시에 포함할지 선택, 종류 : all/non-lazy, 기본값 : all
- 환경설정
1. 의존성 추가하기
<dependency>
<groupId> org.hibernate</groupId>
<artifactId> hibernate-ehcache</artifactId>
<version> 5.6.4.Final</version>
</dependency>
implementation 'org.hibernate:hibernate-ehcache:5.6.4.Final'
1
2. properties 파일에 속성 값 추가하기
#2차 캐시 활성화
spring.jpa.properties.hibernate.cache.use_second_level_cache = true
#2차 캐시를 처리할 클래스를 지정
spring.jpa.properties.hibernate.cache.region.factory_class = org.hibernate.cache.ehcache.EhCacheRegionFactory
#캐시 적용 여부를 확인 (하이버네이트 자체 제공 기능)
spring.jpa.properties.hibernate.generate_statistics = true
1
2
3
4
5
6
7
8
9
10
- 하이버네이트가 지원하는 캐시
- 엔티티 캐시
(1) 엔티티 단위로 캐시한다.
(2) 식별자로 엔티티를 조회하거나 컬렉션이 아닌 연관된 엔티티를 로딩할 때 사용한다.
- 컬렉션 캐시
(1) 엔티티와 연관된 컬렉션을 캐시한다.
(2) 컬렉션이 엔티티를 담고 있으면 식별자 값만 캐시한다.
- 쿼리 캐시
(1) 쿼리와 파라미터 정보를 키로 사용해서 캐시한다.
(2) 결과가 엔티티면 식별자 값만 캐시한다.
//Entity Manager 범위 적용
em . setProperty ( "javax.persistence.cache.retrieveMode" , CacheRetrieveMode . BYPASS );
//find()
Map & lt ; String , Object & gt ; param = new HashMap & lt ; String , Object & gt ;();
param . put ( "javax.persistence.cache.retrieveMode" , CacheRetrieveMode . BYPASS );
param . put ( "javax.persistence.cache.storeMode" , CacheStoreMode . BYPASS );
em . find ( SomeEntity . class , id , param );